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 # import rajoutés suite à l'ajout de Build_sd --> à résorber
30 from Noyau import N_Exception
31 from Noyau.N_Exception import AsException
32 # fin import à résorber
37 class ETAPE(I_MCCOMPO.MCCOMPO):
43 if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
45 if self.reuse != None:
46 sdname= self.reuse.get_name()
48 if self.sd:sdname=self.sd.get_name()
49 if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1:
50 # dans le cas où la SD est 'sansnom' ou 'SD_' on retourne la chaîne vide
54 def is_reentrant(self):
56 Indique si la commande est reentrante
58 return self.definition.reentrant == 'o'
62 Met l'état de l'étape à : modifié
63 Propage la modification au parent
66 # doit etre realisée apres init_modif et la validite reevaluée
67 # apres cette action. L'état modified de tous les objets doit etre
69 self.state = 'modified'
71 self.parent.init_modif()
75 Méthode appelée une fois qu'une modification a été faite afin de
76 déclencher d'éventuels traitements post-modification
77 ex : INCLUDE et POURSUITE
80 d=self.parent.get_contexte_apres(self)
82 self.parent.fin_modif()
84 def nomme_sd(self,nom) :
86 Cette méthode a pour fonction de donner un nom (nom) au concept
87 produit par l'étape (self).
88 - si le concept n'existe pas, on essaye de le créer (à condition que l'étape soit valide ET non réentrante)
89 - si il existe déjà, on le renomme et on répercute les changements dans les autres étapes
90 Les valeurs de retour sont :
91 0 si le nommage n'a pas pu etre mené à son terme,
92 1 dans le cas contraire
94 if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
95 return 0,"Nom de concept trop long (maxi 8 caractères)"
98 # On verifie d'abord si les mots cles sont valides
100 if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
102 # Cas particulier des opérateurs obligatoirement réentrants
104 if self.definition.reentrant == 'o':
105 self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
107 self.sdnom=self.sd.nom
108 return 1,"Concept existant"
110 return 0,"Opérateur réentrant mais concept non existant"
112 # Cas particulier des opérateurs facultativement réentrants
115 if self.definition.reentrant == 'f' :
116 sd = self.jdc.get_sd_avant_etape(nom,self)
118 # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!!
119 if isinstance(sd,self.get_type_produit()) :
120 self.sd = self.reuse = sd
122 return 1,"Opérateur facultativement réentrant et concept existant trouvé"
124 return 0,"Concept déjà existant et de mauvais type"
126 # il faut enlever le lien vers une SD existante car si on passe ici
127 # cela signifie que l'opérateur n'est pas utilisé en mode réentrant.
128 # Si on ne fait pas cela, on risque de modifier une SD produite par un autre opérateur
131 self.sd = self.reuse = self.sdnom = None
133 # On est dans le cas ou l'opérateur n'est pas réentrant ou est facultativement reentrant
134 # mais est utilisé en mode non réentrant
137 if self.parent.get_sd_autour_etape(nom,self):
138 # Un concept de ce nom existe dans le voisinage de l'etape courante
139 # On retablit l'ancien concept reentrant s'il existait
141 self.sd=self.reuse=old_reuse
142 self.sdnom=old_reuse.nom
143 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
145 # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
146 # On peut donc créer le concept retourné.
147 # Il est créé sans nom mais enregistré dans la liste des concepts existants
149 # Il suffit de changer son attribut nom pour le nommer
152 return 1,"Nommage du concept effectué"
155 if string.find(old_nom,'sansnom') :
156 # Dans le cas où old_nom == sansnom, isvalid retourne 0 alors que ...
157 # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'étape est valide
158 # on peut donc le nommer sans test préalable
159 if self.parent.get_sd_autour_etape(nom,self):
160 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
164 return 1,"Nommage du concept effectué"
166 # Normalement l appel de isvalid a mis a jour le concept produit (son type)
167 # Il suffit de spécifier l attribut nom de sd pour le nommer si le nom n est pas
169 if self.parent.get_sd_autour_etape(nom,self):
170 return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
174 return 1,"Nommage du concept effectué"
176 # Normalement on ne devrait pas passer ici
177 return 0,'Normalement on ne devrait pas passer ici'
179 def get_sdprods(self,nom_sd):
181 Fonction : retourne le concept produit par l etape de nom nom_sd
182 s il existe sinon None
185 if self.sd.nom == nom_sd:return self.sd
189 Rend l'etape courante active.
190 Il faut ajouter la sd si elle existe au contexte global du JDC
195 if not self.sd : return
197 self.jdc.append_sdprod(self.sd)
203 Rend l'etape courante inactive
204 Il faut supprimer la sd du contexte global du JDC
205 et de la liste des sd
208 if not self.sd : return
209 self.jdc.del_sdprod(self.sd)
210 self.jdc.delete_concept_after_etape(self,self.sd)
212 def control_sdprods(self,d):
214 Cette methode doit updater le contexte fournit par
215 l'appelant en argument (d) en fonction de sa definition
216 tout en verifiant que ses concepts produits ne sont pas
217 deja definis dans le contexte
219 if type(self.definition.op_init) == types.FunctionType:
220 apply(self.definition.op_init,(self,d))
222 if d.has_key(self.sd.nom):
223 # Le concept est deja defini
224 if self.reuse and self.reuse is d[self.sd.nom]:
225 # Le concept est reutilise : situation normale
228 # Redefinition du concept, on l'annule
229 #XXX on pourrait simplement annuler son nom pour conserver les objets
230 # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
231 self.sd=self.reuse=self.sdnom=None
234 # Le concept n'est pas defini, on peut updater d
235 d[self.sd.nom]=self.sd
237 def supprime_sdprods(self):
240 Lors d'une destruction d'etape, detruit tous les concepts produits
241 Un opérateur n a qu un concept produit
242 Une procedure n'en a aucun
243 Une macro en a en général plus d'un
245 if not self.is_reentrant() :
246 # l'étape n'est pas réentrante
247 # le concept retourné par l'étape est à supprimer car il était
250 self.parent.del_sdprod(self.sd)
251 self.parent.delete_concept(self.sd)
253 def delete_concept(self,sd):
258 Mettre a jour les mots cles de l etape et eventuellement
259 le concept produit si reuse
260 suite à la disparition du concept sd
261 Seuls les mots cles simples MCSIMP font un traitement autre
262 que de transmettre aux fils
264 if self.reuse and self.reuse == sd:
265 self.sd=self.reuse=None
267 for child in self.mc_liste :
268 child.delete_concept(sd)
270 def replace_concept(self,old_sd,sd):
273 old_sd=concept remplace
276 Mettre a jour les mots cles de l etape et eventuellement
277 le concept produit si reuse
278 suite au remplacement du concept old_sd
280 if self.reuse and self.reuse == old_sd:
281 self.sd=self.reuse=sd
283 for child in self.mc_liste :
284 child.replace_concept(old_sd,sd)
286 def make_register(self):
288 Initialise les attributs jdc, id, niveau et réalise les
289 enregistrements nécessaires
290 Pour EFICAS, on tient compte des niveaux
291 Surcharge la methode make_register du package Noyau
294 self.jdc = self.parent.get_jdc_root()
295 self.id= self.parent.register(self)
296 if self.definition.niveau :
297 # La définition est dans un niveau. En plus on
298 # l'enregistre dans le niveau
299 self.nom_niveau_definition = self.definition.niveau.nom
300 self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
301 self.niveau.register(self)
303 # La définition est au niveau global
304 self.nom_niveau_definition = 'JDC'
305 self.niveau=self.parent
307 self.jdc = self.parent =None
312 """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
317 etape.state = 'modified'
322 for objet in self.mc_liste:
323 new_obj = objet.copy()
324 new_obj.reparent(etape)
325 etape.mc_liste.append(new_obj)
328 def get_noms_sd_oper_reentrant(self):
330 Retourne la liste des noms de concepts utilisés à l'intérieur de la commande
331 qui sont du type que peut retourner cette commande
333 liste_sd = self.get_sd_utilisees()
335 if type(self.definition.sd_prod) == types.FunctionType:
336 d=self.cree_dict_valeurs(self.mc_liste)
338 classe_sd_prod = apply(self.definition.sd_prod,(),d)
342 classe_sd_prod = self.definition.sd_prod
344 if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
348 def get_sd_utilisees(self):
350 Retourne la liste des concepts qui sont utilisés à l'intérieur d'une commande
351 ( comme valorisation d'un MCS)
354 for child in self.mc_liste:
355 l.extend(child.get_sd_utilisees())
358 def get_genealogie(self):
360 Retourne la liste des noms des ascendants de l'objet self
361 en s'arretant à la première ETAPE rencontrée
365 def reparent(self,parent):
367 Cette methode sert a reinitialiser la parente de l'objet
370 self.jdc=parent.get_jdc_root()
372 for mocle in self.mc_liste:
375 def verif_existence_sd(self):
377 Vérifie que les structures de données utilisées dans self existent bien dans le contexte
378 avant étape, sinon enlève la référence à ces concepts
380 for motcle in self.mc_liste :
381 motcle.verif_existence_sd()
383 def Build_sd(self,nom):
385 Construit le concept produit de l'opérateur. Deux cas
386 peuvent se présenter :
388 - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création
389 et le nommage du concept.
391 - le parent est défini. Dans ce cas, l'étape demande au parent la création et
392 le nommage du concept.
395 if not self.isactif():return
396 # FR : attention cette méthode ne devrait pas se trouver là car elle surcharge celle qui
397 # se trouve dans N_ETAPE.py et elle est partie intégrante du noyau, mais, suite à l'absence de
398 # test de validité de l'opérateur avant d'essayer de déterminer la sd produite, on n'arrivait
399 # pas à relire avec EFICAS un fichier contenant une étape encore incomplète du style :
400 # sansnom = AFFE_CHAR_CINE(MODELE=None)
401 # Suite à la stabilisation du noyau d'Aster, je n'ai pas eu d'autre solution que de surcharger
402 # cette méthode ici en rajoutant le test manquant ...
403 # CCAR : cette modification ne corrige le probleme qu'en partie. Il faudrait probablement
404 # supprimer les erreurs fatales (exception ) et retourner systematiquement un objet produit
405 # meme en cas d'erreur et reporter l'emission du message d'erreur a la phase de validation
407 if not self.isvalid(sd='non') : return
411 sd= self.parent.create_sdprod(self,nom)
412 if type(self.definition.op_init) == types.FunctionType:
413 apply(self.definition.op_init,(self,self.parent.g_context))
415 sd=self.get_sd_prod()
416 # On n'utilise pas self.definition.op_init car self.parent
418 if sd != None and self.reuse == None:
419 # On ne nomme le concept que dans le cas de non reutilisation
422 if self.jdc and self.jdc.par_lot == "NON" :
425 except AsException,e:
426 # Une erreur s'est produite lors de la construction du concept
427 # Comme on est dans EFICAS, on essaie de poursuivre quand meme
428 # Si on poursuit, on a le choix entre deux possibilités :
429 # 1. on annule la sd associée à self
430 # 2. on la conserve mais il faut la retourner
431 # En plus il faut rendre coherents sdnom et sd.nom
434 self.state="unchanged"
438 #raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
439 # 'fichier : ',self.appel[1],e)
441 # XXX Normalement le contexte courant doit etre le parent.
442 # Il n'y a pas de raison de remettre le contexte au parent
443 #self.reset_current_step()
446 l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
447 raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
448 'fichier : ',self.appel[1]+'\n',