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.
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.
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.
19 # ======================================================================
27 # Objet re pour controler les identificateurs Python
28 concept_re=re.compile(r'[a-zA-Z_]\w*$')
30 # import rajoutés suite à l'ajout de Build_sd --> à résorber
33 from Noyau import N_Exception
34 from Noyau.N_Exception import AsException
35 # fin import à résorber
40 class ETAPE(I_MCCOMPO.MCCOMPO):
46 if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
48 if self.reuse != None:
49 sdname= self.reuse.get_name()
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
57 def is_reentrant(self):
59 Indique si la commande est reentrante
61 return self.definition.reentrant == 'o'
65 Met l'état de l'étape à : modifié
66 Propage la modification au parent
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
72 self.state = 'modified'
74 self.parent.init_modif()
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
83 d=self.parent.get_contexte_apres(self)
85 self.parent.fin_modif()
87 def nomme_sd(self,nom) :
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
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"
101 if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
102 return 0,"Nom de concept trop long (maxi 8 caractères)"
106 # On verifie d'abord si les mots cles sont valides
108 if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
110 # Cas particulier des opérateurs obligatoirement réentrants
112 if self.definition.reentrant == 'o':
113 self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
115 self.sdnom=self.sd.nom
116 return 1,"Concept existant"
118 return 0,"Opérateur réentrant mais concept non existant"
120 # Cas particulier des opérateurs facultativement réentrants
123 if self.definition.reentrant == 'f' :
124 sd = self.jdc.get_sd_avant_etape(nom,self)
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
130 return 1,"Opérateur facultativement réentrant et concept existant trouvé"
132 return 0,"Concept déjà existant et de mauvais type"
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
139 self.sd = self.reuse = self.sdnom = None
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
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
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"
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
158 # Il suffit de changer son attribut nom pour le nommer
161 return 1,"Nommage du concept effectué"
163 return 0,"Nommage impossible"+str(sys.exc_info()[1])
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"
175 return 1,"Nommage du concept effectué"
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
180 if self.parent.get_sd_autour_etape(nom,self):
181 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
185 return 1,"Nommage du concept effectué"
187 # Normalement on ne devrait pas passer ici
188 return 0,'Normalement on ne devrait pas passer ici'
190 def get_sdprods(self,nom_sd):
192 Fonction : retourne le concept produit par l etape de nom nom_sd
193 s il existe sinon None
196 if self.sd.nom == nom_sd:return self.sd
200 Rend l'etape courante active.
201 Il faut ajouter la sd si elle existe au contexte global du JDC
206 if not self.sd : return
208 self.jdc.append_sdprod(self.sd)
214 Rend l'etape courante inactive
215 Il faut supprimer la sd du contexte global du JDC
216 et de la liste des sd
219 if not self.sd : return
220 self.jdc.del_sdprod(self.sd)
221 self.jdc.delete_concept_after_etape(self,self.sd)
223 def control_sdprods(self,d):
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
230 if type(self.definition.op_init) == types.FunctionType:
231 apply(self.definition.op_init,(self,d))
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
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
245 # Le concept n'est pas defini, on peut updater d
246 d[self.sd.nom]=self.sd
248 def supprime_sdprods(self):
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
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
261 self.parent.del_sdprod(self.sd)
262 self.parent.delete_concept(self.sd)
264 def delete_concept(self,sd):
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
275 if self.reuse and self.reuse == sd:
276 self.sd=self.reuse=None
278 for child in self.mc_liste :
279 child.delete_concept(sd)
281 def replace_concept(self,old_sd,sd):
284 - old_sd=concept remplace
285 - sd = nouveau concept
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
291 if self.reuse and self.reuse == old_sd:
292 self.sd=self.reuse=sd
294 for child in self.mc_liste :
295 child.replace_concept(old_sd,sd)
297 def get_noms_sd_oper_reentrant(self):
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
302 liste_sd = self.get_sd_utilisees()
304 if type(self.definition.sd_prod) == types.FunctionType:
305 d=self.cree_dict_valeurs(self.mc_liste)
307 classe_sd_prod = apply(self.definition.sd_prod,(),d)
311 classe_sd_prod = self.definition.sd_prod
313 if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
317 def get_genealogie(self):
319 Retourne la liste des noms des ascendants de l'objet self
320 en s'arretant à la première ETAPE rencontrée
324 def verif_existence_sd(self):
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
329 for motcle in self.mc_liste :
330 motcle.verif_existence_sd()
332 #ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau
333 def Build_sd(self,nom):
335 Methode de Noyau surchargee pour poursuivre malgre tout
336 si une erreur se produit pendant la creation du concept produit
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
350 self.state="unchanged"
355 #ATTENTION SURCHARGE: cette methode doit etre gardée en synchronisation avec Noyau
356 def make_register(self):
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
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)
373 # La définition est au niveau global
374 self.nom_niveau_definition = 'JDC'
375 self.niveau=self.parent
377 self.jdc = self.parent =None