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.
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.
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.
20 # ======================================================================
28 # Objet re pour controler les identificateurs Python
29 concept_re=re.compile(r'[a-zA-Z_]\w*$')
31 # import rajoutés suite à l'ajout de Build_sd --> à résorber
34 from Noyau import N_Exception
35 from Noyau.N_Exception import AsException
36 # fin import à résorber
41 class ETAPE(I_MCCOMPO.MCCOMPO):
47 if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
49 if self.reuse != None:
50 sdname= self.reuse.get_name()
52 if self.sd:sdname=self.sd.get_name()
53 if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1:
54 # dans le cas où la SD est 'sansnom' ou 'SD_' on retourne la chaîne vide
58 def is_reentrant(self):
60 Indique si la commande est reentrante
62 return self.definition.reentrant == 'o'
66 Met l'état de l'étape à : modifié
67 Propage la modification au parent
69 # init_modif doit etre appelé avant de réaliser une modification
70 # La validité devra etre recalculée apres cette modification
71 # mais dans l'appel à fin_modif pour préserver l'état modified
72 # de tous les objets entre temps
73 print "init_modif",self,self.parent
74 self.state = 'modified'
76 self.parent.init_modif()
80 Méthode appelée une fois qu'une modification a été faite afin de
81 déclencher d'éventuels traitements post-modification
82 ex : INCLUDE et POURSUITE
84 print "fin_modif",self,self.parent
86 d=self.parent.get_contexte_apres(self)
88 self.parent.fin_modif()
90 def nomme_sd(self,nom) :
92 Cette méthode a pour fonction de donner un nom (nom) au concept
93 produit par l'étape (self).
94 - si le concept n'existe pas, on essaye de le créer (à condition que l'étape soit valide ET non réentrante)
95 - si il existe déjà, on le renomme et on répercute les changements dans les autres étapes
96 Les valeurs de retour sont :
97 - 0 si le nommage n'a pas pu etre mené à son terme,
98 - 1 dans le cas contraire
100 # Le nom d'un concept doit etre un identificateur Python (toujours vrai ?)
101 if not concept_re.match(nom):
102 return 0,"Un nom de concept doit etre un identificateur Python"
104 if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
105 return 0,"Nom de concept trop long (maxi 8 caractères)"
109 # On verifie d'abord si les mots cles sont valides
111 if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
113 # Cas particulier des opérateurs obligatoirement réentrants
115 if self.definition.reentrant == 'o':
116 self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
118 self.sdnom=self.sd.nom
120 return 1,"Concept existant"
122 return 0,"Opérateur réentrant mais concept non existant"
124 # Cas particulier des opérateurs facultativement réentrants
127 if self.definition.reentrant == 'f' :
128 sd = self.jdc.get_sd_avant_etape(nom,self)
130 # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!!
131 if isinstance(sd,self.get_type_produit()) :
132 self.sd = self.reuse = sd
135 return 1,"Opérateur facultativement réentrant et concept existant trouvé"
137 return 0,"Concept déjà existant et de mauvais type"
139 # il faut enlever le lien vers une SD existante car si on passe ici
140 # cela signifie que l'opérateur n'est pas utilisé en mode réentrant.
141 # Si on ne fait pas cela, on risque de modifier une SD produite par un autre opérateur
144 self.sd = self.reuse = self.sdnom = None
146 # On est dans le cas ou l'opérateur n'est pas réentrant ou est facultativement reentrant
147 # mais est utilisé en mode non réentrant
150 if self.parent.get_sd_autour_etape(nom,self):
151 # Un concept de ce nom existe dans le voisinage de l'etape courante
152 # On retablit l'ancien concept reentrant s'il existait
154 self.sd=self.reuse=old_reuse
155 self.sdnom=old_reuse.nom
156 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
158 # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
159 # On peut donc créer le concept retourné.
160 # Il est créé sans nom mais enregistré dans la liste des concepts existants
163 # Il suffit de changer son attribut nom pour le nommer
167 return 1,"Nommage du concept effectué"
169 return 0,"Nommage impossible"+str(sys.exc_info()[1])
172 if string.find(old_nom,'sansnom') :
173 # Dans le cas où old_nom == sansnom, isvalid retourne 0 alors que ...
174 # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'étape est valide
175 # on peut donc le nommer sans test préalable
176 if self.parent.get_sd_autour_etape(nom,self):
177 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
182 return 1,"Nommage du concept effectué"
184 # Normalement l appel de isvalid a mis a jour le concept produit (son type)
185 # Il suffit de spécifier l attribut nom de sd pour le nommer si le nom n est pas
187 if self.parent.get_sd_autour_etape(nom,self):
188 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
193 return 1,"Nommage du concept effectué"
195 # Normalement on ne devrait pas passer ici
196 return 0,'Normalement on ne devrait pas passer ici'
198 def get_sdprods(self,nom_sd):
200 Fonction : retourne le concept produit par l etape de nom nom_sd
201 s il existe sinon None
204 if self.sd.nom == nom_sd:return self.sd
208 Rend l'etape courante active.
209 Il faut ajouter la sd si elle existe au contexte global du JDC
214 if not self.sd : return
216 self.jdc.append_sdprod(self.sd)
222 Rend l'etape courante inactive
223 Il faut supprimer la sd du contexte global du JDC
224 et de la liste des sd
227 if not self.sd : return
228 self.jdc.del_sdprod(self.sd)
229 self.jdc.delete_concept_after_etape(self,self.sd)
231 def control_sdprods(self,d):
233 Cette methode doit updater le contexte fournit par
234 l'appelant en argument (d) en fonction de sa definition
235 tout en verifiant que ses concepts produits ne sont pas
236 deja definis dans le contexte
238 if type(self.definition.op_init) == types.FunctionType:
239 apply(self.definition.op_init,(self,d))
241 if d.has_key(self.sd.nom):
242 # Le concept est deja defini
243 if self.reuse and self.reuse is d[self.sd.nom]:
244 # Le concept est reutilise : situation normale
247 # Redefinition du concept, on l'annule
248 #XXX on pourrait simplement annuler son nom pour conserver les objets
249 # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
250 self.sd=self.reuse=self.sdnom=None
253 # Le concept n'est pas defini, on peut updater d
254 d[self.sd.nom]=self.sd
256 def supprime_sdprods(self):
259 Lors d'une destruction d'etape, detruit tous les concepts produits
260 Un opérateur n a qu un concept produit
261 Une procedure n'en a aucun
262 Une macro en a en général plus d'un
264 if not self.is_reentrant() :
265 # l'étape n'est pas réentrante
266 # le concept retourné par l'étape est à supprimer car il était
269 self.parent.del_sdprod(self.sd)
270 self.parent.delete_concept(self.sd)
272 def delete_concept(self,sd):
277 Mettre a jour les mots cles de l etape et eventuellement
278 le concept produit si reuse
279 suite à la disparition du concept sd
280 Seuls les mots cles simples MCSIMP font un traitement autre
281 que de transmettre aux fils
283 if self.reuse and self.reuse == sd:
284 self.sd=self.reuse=None
286 for child in self.mc_liste :
287 child.delete_concept(sd)
289 def replace_concept(self,old_sd,sd):
292 - old_sd=concept remplace
293 - sd = nouveau concept
295 Mettre a jour les mots cles de l etape et eventuellement
296 le concept produit si reuse
297 suite au remplacement du concept old_sd
299 if self.reuse and self.reuse == old_sd:
300 self.sd=self.reuse=sd
302 for child in self.mc_liste :
303 child.replace_concept(old_sd,sd)
305 def get_noms_sd_oper_reentrant(self):
307 Retourne la liste des noms de concepts utilisés à l'intérieur de la commande
308 qui sont du type que peut retourner cette commande
310 liste_sd = self.get_sd_utilisees()
312 if type(self.definition.sd_prod) == types.FunctionType:
313 d=self.cree_dict_valeurs(self.mc_liste)
315 classe_sd_prod = apply(self.definition.sd_prod,(),d)
319 classe_sd_prod = self.definition.sd_prod
321 if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
325 def get_genealogie(self):
327 Retourne la liste des noms des ascendants de l'objet self
328 en s'arretant à la première ETAPE rencontrée
332 def verif_existence_sd(self):
334 Vérifie que les structures de données utilisées dans self existent bien dans le contexte
335 avant étape, sinon enlève la référence à ces concepts
337 for motcle in self.mc_liste :
338 motcle.verif_existence_sd()
340 #ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau
341 def Build_sd(self,nom):
343 Methode de Noyau surchargee pour poursuivre malgre tout
344 si une erreur se produit pendant la creation du concept produit
347 sd=Noyau.N_ETAPE.ETAPE.Build_sd(self,nom)
348 except AsException,e:
349 # Une erreur s'est produite lors de la construction du concept
350 # Comme on est dans EFICAS, on essaie de poursuivre quand meme
351 # Si on poursuit, on a le choix entre deux possibilités :
352 # 1. on annule la sd associée à self
353 # 2. on la conserve mais il faut la retourner
354 # En plus il faut rendre coherents sdnom et sd.nom
357 self.state="unchanged"
362 #ATTENTION SURCHARGE: cette methode doit etre gardée en synchronisation avec Noyau
363 def make_register(self):
365 Initialise les attributs jdc, id, niveau et réalise les
366 enregistrements nécessaires
367 Pour EFICAS, on tient compte des niveaux
368 Surcharge la methode make_register du package Noyau
371 self.jdc = self.parent.get_jdc_root()
372 self.id= self.parent.register(self)
373 if self.definition.niveau :
374 # La définition est dans un niveau. En plus on
375 # l'enregistre dans le niveau
376 self.nom_niveau_definition = self.definition.niveau.nom
377 self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
378 self.niveau.register(self)
380 # La définition est au niveau global
381 self.nom_niveau_definition = 'JDC'
382 self.niveau=self.parent
384 self.jdc = self.parent =None