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 # ======================================================================
23 import types,traceback
24 import string,linecache
28 from Noyau.N_ASSD import ASSD
29 from Noyau.N_ETAPE import ETAPE
30 from Noyau.N_Exception import AsException
31 from Extensions import commentaire,parametre,parametre_eval
33 class JDC(I_OBJECT.OBJECT):
38 self.etapes_niveaux=[]
42 self._etape_context=None
43 self.recorded_units={}
44 self.old_recorded_units={}
46 def get_sd_avant_du_bon_type(self,etape,types_permis):
48 Retourne la liste des concepts avant etape d'un type acceptable
50 d=self.get_contexte_avant(etape)
53 if type(v) != types.InstanceType : continue
54 # On considère que seul assd indique un type quelconque pas CO
55 elif self.assd in types_permis :
57 elif self.est_permis(v,types_permis):
62 def est_permis(self,v,types_permis):
63 for type_ok in types_permis:
64 if type_ok in ('R','I','C','TXM') and v in self.params :
66 elif type_ok == 'R' and v.__class__.__name__ == 'reel' :
68 elif type_ok == 'I' and v.__class__.__name__ == 'entier' :
70 elif type_ok == 'C' and v.__class__.__name__ == 'complexe' :
72 elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' :
74 elif type(type_ok) != types.ClassType :
76 elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
80 def addentite(self,name,pos):
83 Si name est le nom d une commande ou un commentaire ajoute
85 Sinon remonte une erreur
89 if name == "COMMENTAIRE" :
90 # ajout d'un commentaire
91 self.set_current_step()
93 for child in self.etapes :
94 if isinstance(child,commentaire.COMMENTAIRE):
96 objet = commentaire.COMMENTAIRE('',parent=self)
97 objet.nom = "_comm_"+`ind`
98 if pos == None : pos = 0
99 self.etapes.insert(pos,objet)
103 elif name == "PARAMETRE":
104 # ajout d'un parametre
105 self.set_current_step()
106 nom_param = '_param_'+str(len(self.params)+1)
107 objet = parametre.PARAMETRE(nom=nom_param)
108 if pos == None : pos = 0
109 self.etapes.insert(pos,objet)
114 elif name == "PARAMETRE_EVAL":
115 # ajout d'un parametre EVAL
116 self.set_current_step()
117 nom_param = '_param_'+str(len(self.params)+1)
118 objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
119 if pos == None : pos = 0
120 self.etapes.insert(pos,objet)
125 elif type(name)==types.InstanceType:
126 # on est dans le cas où on veut ajouter une commande déjà
127 # existante (par copie donc)
128 # on est donc nécessairement en mode editeur ...
130 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
132 self.set_current_step()
133 if isinstance(objet,ETAPE):
134 if objet.nom_niveau_definition == 'JDC':
135 # l'objet dépend directement du JDC
138 # l'étape dépend d'un niveau et non directement du JDC :
139 # il faut l'enregistrer dans le niveau de parent
140 objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
141 objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
142 self.etapes.insert(pos,objet)
143 # il faut vérifier que les concepts utilisés par objet existent bien
144 # à ce niveau d'arborescence
145 objet.verif_existence_sd()
151 # On veut ajouter une nouvelle commande
153 self.set_current_step()
154 cmd=self.get_cmd(name)
155 # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
156 # auprès du step courant car editmode vaut 1
157 # Par contre elle a le bon parent grace a set_current_step
159 if pos == None : pos = 0
160 self.etapes.insert(pos,e)
161 self.reset_current_step()
166 except AsException,e:
167 self.reset_current_step()
169 raise AsException("Impossible d ajouter la commande "+name + '\n' +str(e))
171 traceback.print_exc()
172 self.reset_current_step()
174 raise AsException("Impossible d ajouter la commande "+name)
176 def set_current_step(self):
177 CONTEXT.unset_current_step()
178 CONTEXT.set_current_step(self)
180 def reset_current_step(self):
181 CONTEXT.unset_current_step()
183 def liste_mc_presents(self):
186 def get_sd_avant_etape(self,nom_sd,etape):
187 return self.get_contexte_avant(etape).get(nom_sd,None)
189 def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
191 Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement
192 définie apres etape en tenant compte des concepts detruits
193 Si avec vaut 'non' exclut etape de la recherche
195 ietap=self.etapes.index(etape)
196 if avec == 'non':ietap=ietap+1
198 for e in self.etapes[ietap:]:
201 autre_sd=d.get(nom_sd,None)
203 # Le concept a ete detruit
205 if autre_sd is not sd :
206 # L'etape produit un concept de meme nom
207 if hasattr(e,'reuse') and e.reuse == autre_sd:
208 # Le concept est reutilise, ce n'est pas un produit de l'etape
211 # Le concept est produit par l'etape
213 # On n'a rien trouve. Pas de concept de nom nom_sd
216 def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
218 Cette méthode retourne la SD de nom nom_sd qui est éventuellement
220 Si avec vaut 'non' exclut etape de la recherche
222 ietap=self.etapes.index(etape)
223 if avec == 'non':ietap=ietap+1
224 for e in self.etapes[ietap:]:
225 sd=e.get_sdprods(nom_sd)
227 if hasattr(e,'reuse'):
232 def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
234 Fonction: retourne la SD de nom nom_sd qui est éventuellement
235 définie avant ou apres etape
236 Permet de vérifier si un concept de meme nom existe dans le périmètre
238 Si avec vaut 'non' exclut etape de la recherche
240 sd=self.get_sd_avant_etape(nom_sd,etape)
242 return self.get_sd_apres_etape(nom_sd,etape,avec)
244 def get_contexte_apres(self,etape):
246 Retourne le dictionnaire des concepts connus apres etape
247 On tient compte des commandes qui modifient le contexte
248 comme DETRUIRE ou les macros
249 Si etape == None, on retourne le contexte en fin de JDC
251 if not etape: return self.get_contexte_avant(etape)
253 d=self.get_contexte_avant(etape)
254 if etape.isactif():etape.update_context(d)
255 self.index_etape_courante=self.index_etape_courante+1
258 def active_etapes(self):
260 Cette méthode a pour fonction de désactiver les étapes qui doivent
261 l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas
262 comprises entre le premier DEBUT/POURSUITE et le premier FIN
263 et rendre actives les autres
265 if self.definition.code == 'ASTER' :
266 # Seulement pour ASTER :
267 # Avant DEBUT actif vaut 0
268 # Apres DEBUT et avant le 1er FIN actif vaut 1
269 # Apres le 1er FIN actif vaut -1
273 for etape in self.etapes:
274 if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
279 if etape.nom == 'FIN':actif=-1
281 def suppentite(self,etape) :
283 Cette methode a pour fonction de supprimer une étape dans
287 # On memorise le contexte avant l'etape a supprimer
288 d=self.get_contexte_avant(etape)
289 index_etape=self.etapes.index(etape)
291 self.etapes.remove(etape)
292 if etape.niveau is not self:
293 # Dans ce cas l'étape est enregistrée dans un niveau
294 # Il faut la désenregistrer
295 etape.niveau.unregister(etape)
296 etape.supprime_sdprods()
299 # Apres suppression de l'etape il faut controler que les etapes
300 # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
301 for e in self.etapes[index_etape:]:
309 if not self.cr.estvide():return
313 def register_parametre(self,param):
315 Cette méthode sert à ajouter un paramètre dans la liste des paramètres
317 self.params.append(param)
319 def register_fonction(self,fonction):
321 Cette méthode sert à ajouter une fonction dans la liste des fonctions
323 self.fonctions.append(fonction)
325 def delete_param(self,param):
327 Supprime le paramètre param de la liste des paramètres
330 if param in self.params : self.params.remove(param)
331 if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
333 def get_parametres_fonctions_avant_etape(self,etape):
335 Retourne deux éléments :
336 - une liste contenant les noms des paramètres (constantes ou EVAL)
338 - une liste contenant les formules définies avant etape
342 # on récupère le contexte avant etape
343 # on ne peut mettre dans les deux listes que des éléments de ce contexte
344 d=self.get_contexte_avant(etape)
345 # construction de l_constantes
346 for param in self.params:
348 if not nom : continue
349 if d.has_key(nom): l_constantes.append(nom)
350 # construction de l_fonctions
351 for form in self.fonctions:
353 if not nom : continue
354 if d.has_key(nom): l_fonctions.append(form.get_formule())
356 # on ajoute les concepts produits par DEFI_VALEUR
357 # XXX On pourrait peut etre faire plutot le test sur le type
358 # de concept : entier, reel, complexe, etc.
359 for k,v in d.items():
360 if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
361 l_constantes.append(k)
363 # on retourne les deux listes
364 return l_constantes,l_fonctions
366 def get_nb_etapes_avant(self,niveau):
368 Retourne le nombre d etapes avant le debut de niveau
371 for niv in self.etapes_niveaux:
372 if niv == niveau:break
373 nb=nb+len(niv.etapes)
376 def send_message(self,message):
378 self.appli.send_message(message)
380 def init_modif(self):
382 Méthode appelée au moment où une modification va être faite afin de
383 déclencher d'éventuels traitements pré-modification
385 self.state = 'modified'
391 def get_liste_mc_inconnus(self):
393 Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
395 # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
397 for etape in self.etapes :
399 if not etape.isvalid() :
400 l = etape.get_liste_mc_inconnus()
401 if l : l_mc.extend(l)
404 def get_genealogie(self):
406 Retourne la liste des noms des ascendants de l'objet self
407 jusqu'à la première ETAPE parent.
411 def set_etape_context(self,etape):
413 Positionne l'etape qui sera utilisee dans NommerSdProd pour
414 decider si le concept passé pourra etre nommé
416 self._etape_context=etape
418 def reset_context(self):
420 Cette methode reinitialise le contexte glissant pour pouvoir
421 tenir compte des modifications de l'utilisateur : création
422 de commandes, nommage de concepts, etc.
424 self.current_context={}
425 self.index_etape_courante=0
427 def del_sdprod(self,sd):
429 Supprime la SD sd de la liste des sd et des dictionnaires de contexte
431 if sd in self.sds : self.sds.remove(sd)
432 if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
433 if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
435 def del_param(self,param):
437 Supprime le paramètre param de la liste des paramètres
440 if param in self.params : self.params.remove(param)
441 if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
443 def del_fonction(self,fonction):
445 Supprime la fonction fonction de la liste des fonctions
448 if fonction in self.fonctions : self.fonctions.remove(fonction)
449 if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
451 def append_sdprod(self,sd):
453 Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
454 même nom n'existe pas déjà
456 if sd == None or sd.nom == None:return
458 o=self.sds_dict.get(sd.nom,None)
459 if isinstance(o,ASSD):
460 raise AsException("Nom de concept deja defini : %s" % sd.nom)
461 self.sds_dict[sd.nom]=sd
462 self.g_context[sd.nom] = sd
463 if sd not in self.sds : self.sds.append(sd)
465 def append_param(self,param):
467 Ajoute le paramètre param à la liste des params
468 et au contexte global
470 # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
471 if param not in self.params : self.params.append(param)
472 self.g_context[param.nom]=param
474 def append_fonction(self,fonction):
476 Ajoute la fonction fonction à la liste des fonctions
477 et au contexte global
479 # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
480 if fonction not in self.fonctions : self.fonctions.append(fonction)
481 self.g_context[fonction.nom]=fonction
483 def delete_concept(self,sd):
488 Mettre a jour les etapes du JDC suite à la disparition du
490 Seuls les mots cles simples MCSIMP font un traitement autre
491 que de transmettre aux fils
493 for etape in self.etapes :
494 etape.delete_concept(sd)
496 def replace_concept_after_etape(self,etape,old_sd,sd):
498 Met à jour les étapes du JDC qui sont après etape en fonction
499 du remplacement du concept sd
501 index = self.etapes.index(etape)+1
502 if index == len(self.etapes) :
503 return # etape est la dernière étape du jdc ...on ne fait rien !
504 for child in self.etapes[index:]:
505 child.replace_concept(old_sd,sd)
507 def dump_state(self):
509 print "JDC.state: ",self.state
510 for etape in self.etapes :
511 print etape.nom+".state: ",etape.state
513 def change_unit(self,unit,etape,old_unit):
514 if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
515 self.record_unit(unit,etape)
517 def record_unit(self,unit,etape):
518 """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
521 self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
523 self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
525 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
526 def register(self,etape):
528 Cette méthode ajoute etape dans la liste
529 des etapes self.etapes et retourne l identificateur d'étape
530 fourni par l appel a g_register
532 A quoi sert editmode ?
533 - Si editmode vaut 1, on est en mode edition de JDC. On cherche
534 à enregistrer une étape que l'on a créée avec eficas (en passant
535 par addentite) auquel cas on ne veut récupérer que son numéro
536 d'enregistrement et c'est addentité qui l'enregistre dans
537 self.etapes à la bonne place...
538 - Si editmode vaut 0, on est en mode relecture d'un fichier de
539 commandes et on doit enregistrer l'étape à la fin de self.etapes
540 (dans ce cas l'ordre des étapes est bien l'ordre chronologique
543 if not self.editmode:
544 self.etapes.append(etape)
547 return self.g_register(etape)
549 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
550 def NommerSdprod(self,sd,sdnom,restrict='non'):
552 Nomme la SD apres avoir verifie que le nommage est possible :
554 Si le nom est deja utilise, leve une exception
555 Met le concept créé dans le concept global g_context
557 # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
558 # Le dictionnaire g_context ne représente pas le contexte
559 # effectif avant une étape.
560 # Il faut utiliser get_contexte_avant avec indication de l'étape
562 # Cette etape est indiquee par l'attribut _etape_context qui a ete
563 # positionné préalablement par un appel à set_etape_context
565 if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
567 if self._etape_context:
568 o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
570 o=self.sds_dict.get(sdnom,None)
572 if isinstance(o,ASSD):
573 raise AsException("Nom de concept deja defini : %s" % sdnom)
575 # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
576 # Ajoute a la creation (appel de reg_sd).
577 self.sds_dict[sdnom]=sd
580 # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
581 if restrict == 'non':
582 self.g_context[sdnom]=sd
584 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
585 def delete_concept_after_etape(self,etape,sd):
587 Met à jour les étapes du JDC qui sont après etape en fonction
588 de la disparition du concept sd
590 index = self.etapes.index(etape)+1
591 if index == len(self.etapes) :
592 return # etape est la dernière étape du jdc ...on ne fait rien !
593 for child in self.etapes[index:]:
594 child.delete_concept(sd)
596 #ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer