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
70 # doit etre realisée apres init_modif et la validite reevaluée
71 # apres cette action. L'état modified de tous les objets doit etre
73 self.state = 'modified'
75 self.parent.init_modif()
79 Méthode appelée une fois qu'une modification a été faite afin de
80 déclencher d'éventuels traitements post-modification
81 ex : INCLUDE et POURSUITE
84 d=self.parent.get_contexte_apres(self)
86 self.parent.fin_modif()
88 def nomme_sd(self,nom) :
90 Cette méthode a pour fonction de donner un nom (nom) au concept
91 produit par l'étape (self).
92 - si le concept n'existe pas, on essaye de le créer (à condition que l'étape soit valide ET non réentrante)
93 - si il existe déjà, on le renomme et on répercute les changements dans les autres étapes
94 Les valeurs de retour sont :
95 - 0 si le nommage n'a pas pu etre mené à son terme,
96 - 1 dans le cas contraire
98 # Le nom d'un concept doit etre un identificateur Python (toujours vrai ?)
99 if not concept_re.match(nom):
100 return 0,"Un nom de concept doit etre un identificateur Python"
102 if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
103 return 0,"Nom de concept trop long (maxi 8 caractères)"
107 # On verifie d'abord si les mots cles sont valides
109 if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
111 # Cas particulier des opérateurs obligatoirement réentrants
113 if self.definition.reentrant == 'o':
114 self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
116 self.sdnom=self.sd.nom
117 return 1,"Concept existant"
119 return 0,"Opérateur réentrant mais concept non existant"
121 # Cas particulier des opérateurs facultativement réentrants
124 if self.definition.reentrant == 'f' :
125 sd = self.jdc.get_sd_avant_etape(nom,self)
127 # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!!
128 if isinstance(sd,self.get_type_produit()) :
129 self.sd = self.reuse = sd
131 return 1,"Opérateur facultativement réentrant et concept existant trouvé"
133 return 0,"Concept déjà existant et de mauvais type"
135 # il faut enlever le lien vers une SD existante car si on passe ici
136 # cela signifie que l'opérateur n'est pas utilisé en mode réentrant.
137 # Si on ne fait pas cela, on risque de modifier une SD produite par un autre opérateur
140 self.sd = self.reuse = self.sdnom = None
142 # On est dans le cas ou l'opérateur n'est pas réentrant ou est facultativement reentrant
143 # mais est utilisé en mode non réentrant
146 if self.parent.get_sd_autour_etape(nom,self):
147 # Un concept de ce nom existe dans le voisinage de l'etape courante
148 # On retablit l'ancien concept reentrant s'il existait
150 self.sd=self.reuse=old_reuse
151 self.sdnom=old_reuse.nom
152 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
154 # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
155 # On peut donc créer le concept retourné.
156 # Il est créé sans nom mais enregistré dans la liste des concepts existants
159 # Il suffit de changer son attribut nom pour le nommer
162 return 1,"Nommage du concept effectué"
164 return 0,"Nommage impossible"+str(sys.exc_info()[1])
167 if string.find(old_nom,'sansnom') :
168 # Dans le cas où old_nom == sansnom, isvalid retourne 0 alors que ...
169 # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'étape est valide
170 # on peut donc le nommer sans test préalable
171 if self.parent.get_sd_autour_etape(nom,self):
172 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
176 return 1,"Nommage du concept effectué"
178 # Normalement l appel de isvalid a mis a jour le concept produit (son type)
179 # Il suffit de spécifier l attribut nom de sd pour le nommer si le nom n est pas
181 if self.parent.get_sd_autour_etape(nom,self):
182 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
186 return 1,"Nommage du concept effectué"
188 # Normalement on ne devrait pas passer ici
189 return 0,'Normalement on ne devrait pas passer ici'
191 def get_sdprods(self,nom_sd):
193 Fonction : retourne le concept produit par l etape de nom nom_sd
194 s il existe sinon None
197 if self.sd.nom == nom_sd:return self.sd
201 Rend l'etape courante active.
202 Il faut ajouter la sd si elle existe au contexte global du JDC
207 if not self.sd : return
209 self.jdc.append_sdprod(self.sd)
215 Rend l'etape courante inactive
216 Il faut supprimer la sd du contexte global du JDC
217 et de la liste des sd
220 if not self.sd : return
221 self.jdc.del_sdprod(self.sd)
222 self.jdc.delete_concept_after_etape(self,self.sd)
224 def control_sdprods(self,d):
226 Cette methode doit updater le contexte fournit par
227 l'appelant en argument (d) en fonction de sa definition
228 tout en verifiant que ses concepts produits ne sont pas
229 deja definis dans le contexte
231 if type(self.definition.op_init) == types.FunctionType:
232 apply(self.definition.op_init,(self,d))
234 if d.has_key(self.sd.nom):
235 # Le concept est deja defini
236 if self.reuse and self.reuse is d[self.sd.nom]:
237 # Le concept est reutilise : situation normale
240 # Redefinition du concept, on l'annule
241 #XXX on pourrait simplement annuler son nom pour conserver les objets
242 # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
243 self.sd=self.reuse=self.sdnom=None
246 # Le concept n'est pas defini, on peut updater d
247 d[self.sd.nom]=self.sd
249 def supprime_sdprods(self):
252 Lors d'une destruction d'etape, detruit tous les concepts produits
253 Un opérateur n a qu un concept produit
254 Une procedure n'en a aucun
255 Une macro en a en général plus d'un
257 if not self.is_reentrant() :
258 # l'étape n'est pas réentrante
259 # le concept retourné par l'étape est à supprimer car il était
262 self.parent.del_sdprod(self.sd)
263 self.parent.delete_concept(self.sd)
265 def delete_concept(self,sd):
270 Mettre a jour les mots cles de l etape et eventuellement
271 le concept produit si reuse
272 suite à la disparition du concept sd
273 Seuls les mots cles simples MCSIMP font un traitement autre
274 que de transmettre aux fils
276 if self.reuse and self.reuse == sd:
277 self.sd=self.reuse=None
279 for child in self.mc_liste :
280 child.delete_concept(sd)
282 def replace_concept(self,old_sd,sd):
285 - old_sd=concept remplace
286 - sd = nouveau concept
288 Mettre a jour les mots cles de l etape et eventuellement
289 le concept produit si reuse
290 suite au remplacement du concept old_sd
292 if self.reuse and self.reuse == old_sd:
293 self.sd=self.reuse=sd
295 for child in self.mc_liste :
296 child.replace_concept(old_sd,sd)
298 def get_noms_sd_oper_reentrant(self):
300 Retourne la liste des noms de concepts utilisés à l'intérieur de la commande
301 qui sont du type que peut retourner cette commande
303 liste_sd = self.get_sd_utilisees()
305 if type(self.definition.sd_prod) == types.FunctionType:
306 d=self.cree_dict_valeurs(self.mc_liste)
308 classe_sd_prod = apply(self.definition.sd_prod,(),d)
312 classe_sd_prod = self.definition.sd_prod
314 if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
318 def get_genealogie(self):
320 Retourne la liste des noms des ascendants de l'objet self
321 en s'arretant à la première ETAPE rencontrée
325 def verif_existence_sd(self):
327 Vérifie que les structures de données utilisées dans self existent bien dans le contexte
328 avant étape, sinon enlève la référence à ces concepts
330 for motcle in self.mc_liste :
331 motcle.verif_existence_sd()
333 #ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau
334 def Build_sd(self,nom):
336 Methode de Noyau surchargee pour poursuivre malgre tout
337 si une erreur se produit pendant la creation du concept produit
340 sd=Noyau.N_ETAPE.ETAPE.Build_sd(self,nom)
341 self.state="modified"
342 except AsException,e:
343 # Une erreur s'est produite lors de la construction du concept
344 # Comme on est dans EFICAS, on essaie de poursuivre quand meme
345 # Si on poursuit, on a le choix entre deux possibilités :
346 # 1. on annule la sd associée à self
347 # 2. on la conserve mais il faut la retourner
348 # En plus il faut rendre coherents sdnom et sd.nom
351 self.state="unchanged"
356 #ATTENTION SURCHARGE: cette methode doit etre gardée en synchronisation avec Noyau
357 def make_register(self):
359 Initialise les attributs jdc, id, niveau et réalise les
360 enregistrements nécessaires
361 Pour EFICAS, on tient compte des niveaux
362 Surcharge la methode make_register du package Noyau
365 self.jdc = self.parent.get_jdc_root()
366 self.id= self.parent.register(self)
367 if self.definition.niveau :
368 # La définition est dans un niveau. En plus on
369 # l'enregistre dans le niveau
370 self.nom_niveau_definition = self.definition.niveau.nom
371 self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
372 self.niveau.register(self)
374 # La définition est au niveau global
375 self.nom_niveau_definition = 'JDC'
376 self.niveau=self.parent
378 self.jdc = self.parent =None