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 # ======================================================================
24 import types,traceback
25 import string,linecache
29 from Noyau.N_ASSD import ASSD
30 from Noyau.N_ETAPE import ETAPE
31 from Noyau.N_Exception import AsException
32 from Extensions import commentaire,parametre,parametre_eval
34 class JDC(I_OBJECT.OBJECT):
39 self.etapes_niveaux=[]
43 self._etape_context=None
44 self.recorded_units={}
45 self.old_recorded_units={}
47 def get_sd_avant_du_bon_type(self,etape,types_permis):
49 Retourne la liste des concepts avant etape d'un type acceptable
51 d=self.get_contexte_avant(etape)
54 if type(v) != types.InstanceType : continue
55 # On considère que seul assd indique un type quelconque pas CO
56 elif self.assd in types_permis :
58 elif self.est_permis(v,types_permis):
63 def est_permis(self,v,types_permis):
64 for type_ok in types_permis:
65 if type_ok in ('R','I','C','TXM') and v in self.params :
67 elif type_ok == 'R' and v.__class__.__name__ == 'reel' :
69 elif type_ok == 'I' and v.__class__.__name__ == 'entier' :
71 elif type_ok == 'C' and v.__class__.__name__ == 'complexe' :
73 elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' :
75 elif type(type_ok) != types.ClassType :
77 elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
81 def addentite(self,name,pos):
84 Si name est le nom d une commande ou un commentaire ajoute
86 Sinon remonte une erreur
90 if name == "COMMENTAIRE" :
91 # ajout d'un commentaire
92 self.set_current_step()
94 for child in self.etapes :
95 if isinstance(child,commentaire.COMMENTAIRE):
97 objet = commentaire.COMMENTAIRE('',parent=self)
98 objet.nom = "_comm_"+`ind`
99 if pos == None : pos = 0
100 self.etapes.insert(pos,objet)
104 elif name == "PARAMETRE":
105 # ajout d'un parametre
106 self.set_current_step()
107 nom_param = '_param_'+str(len(self.params)+1)
108 objet = parametre.PARAMETRE(nom=nom_param)
109 if pos == None : pos = 0
110 self.etapes.insert(pos,objet)
115 elif name == "PARAMETRE_EVAL":
116 # ajout d'un parametre EVAL
117 self.set_current_step()
118 nom_param = '_param_'+str(len(self.params)+1)
119 objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
120 if pos == None : pos = 0
121 self.etapes.insert(pos,objet)
126 elif type(name)==types.InstanceType:
127 # on est dans le cas où on veut ajouter une commande déjà
128 # existante (par copie donc)
129 # on est donc nécessairement en mode editeur ...
131 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
133 self.set_current_step()
134 if isinstance(objet,ETAPE):
135 if objet.nom_niveau_definition == 'JDC':
136 # l'objet dépend directement du JDC
139 # l'étape dépend d'un niveau et non directement du JDC :
140 # il faut l'enregistrer dans le niveau de parent
141 objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
142 objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
143 self.etapes.insert(pos,objet)
144 # il faut vérifier que les concepts utilisés par objet existent bien
145 # à ce niveau d'arborescence
146 objet.verif_existence_sd()
152 # On veut ajouter une nouvelle commande
154 self.set_current_step()
155 cmd=self.get_cmd(name)
156 # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
157 # auprès du step courant car editmode vaut 1
158 # Par contre elle a le bon parent grace a set_current_step
160 if pos == None : pos = 0
161 self.etapes.insert(pos,e)
162 self.reset_current_step()
167 except AsException,e:
168 self.reset_current_step()
170 raise AsException("Impossible d ajouter la commande "+name + '\n' +str(e))
172 traceback.print_exc()
173 self.reset_current_step()
175 raise AsException("Impossible d ajouter la commande "+name)
177 def set_current_step(self):
178 CONTEXT.unset_current_step()
179 CONTEXT.set_current_step(self)
181 def reset_current_step(self):
182 CONTEXT.unset_current_step()
184 def liste_mc_presents(self):
187 def get_sd_avant_etape(self,nom_sd,etape):
188 return self.get_contexte_avant(etape).get(nom_sd,None)
190 def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
192 Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement
193 définie apres etape en tenant compte des concepts detruits
194 Si avec vaut 'non' exclut etape de la recherche
196 ietap=self.etapes.index(etape)
197 if avec == 'non':ietap=ietap+1
199 for e in self.etapes[ietap:]:
202 autre_sd=d.get(nom_sd,None)
204 # Le concept a ete detruit
206 if autre_sd is not sd :
207 # L'etape produit un concept de meme nom
208 if hasattr(e,'reuse') and e.reuse == autre_sd:
209 # Le concept etant reutilise, on interrompt la recherche.
210 # On considere qu'il n'y a pas de nouveau concept defini
211 # meme si dans les etapes suivantes le concept est detruit
212 # et un concept de meme nom créé.
215 # Le concept est produit par l'etape
217 # On n'a rien trouve. Pas de concept de nom nom_sd
220 def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
222 Cette méthode retourne la SD de nom nom_sd qui est éventuellement
224 Si avec vaut 'non' exclut etape de la recherche
226 ietap=self.etapes.index(etape)
227 if avec == 'non':ietap=ietap+1
228 for e in self.etapes[ietap:]:
229 sd=e.get_sdprods(nom_sd)
231 if hasattr(e,'reuse'):
236 def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
238 Fonction: retourne la SD de nom nom_sd qui est éventuellement
239 définie avant ou apres etape
240 Permet de vérifier si un concept de meme nom existe dans le périmètre
242 Si avec vaut 'non' exclut etape de la recherche
244 sd=self.get_sd_avant_etape(nom_sd,etape)
246 return self.get_sd_apres_etape(nom_sd,etape,avec)
248 def get_contexte_apres(self,etape):
250 Retourne le dictionnaire des concepts connus apres etape
251 On tient compte des commandes qui modifient le contexte
252 comme DETRUIRE ou les macros
253 Si etape == None, on retourne le contexte en fin de JDC
255 if not etape: return self.get_contexte_avant(etape)
257 d=self.get_contexte_avant(etape)
258 if etape.isactif():etape.update_context(d)
259 self.index_etape_courante=self.index_etape_courante+1
262 def active_etapes(self):
264 Cette méthode a pour fonction de désactiver les étapes qui doivent
265 l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas
266 comprises entre le premier DEBUT/POURSUITE et le premier FIN
267 et rendre actives les autres
269 if self.definition.code == 'ASTER' :
270 # Seulement pour ASTER :
271 # Avant DEBUT actif vaut 0
272 # Apres DEBUT et avant le 1er FIN actif vaut 1
273 # Apres le 1er FIN actif vaut -1
277 for etape in self.etapes:
278 if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
283 if etape.nom == 'FIN':actif=-1
285 def suppentite(self,etape) :
287 Cette methode a pour fonction de supprimer une étape dans
289 Retourne 1 si la suppression a pu être effectuée,
290 Retourne 0 dans le cas contraire
293 # On memorise le contexte avant l'etape a supprimer
294 d=self.get_contexte_avant(etape)
295 index_etape=self.etapes.index(etape)
297 self.etapes.remove(etape)
298 if etape.niveau is not self:
299 # Dans ce cas l'étape est enregistrée dans un niveau
300 # Il faut la désenregistrer
301 etape.niveau.unregister(etape)
302 etape.supprime_sdprods()
305 # Apres suppression de l'etape il faut controler que les etapes
306 # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
307 for e in self.etapes[index_etape:]:
316 if not self.cr.estvide():return
320 def register_parametre(self,param):
322 Cette méthode sert à ajouter un paramètre dans la liste des paramètres
324 self.params.append(param)
326 def register_fonction(self,fonction):
328 Cette méthode sert à ajouter une fonction dans la liste des fonctions
330 self.fonctions.append(fonction)
332 def delete_param(self,param):
334 Supprime le paramètre param de la liste des paramètres
337 if param in self.params : self.params.remove(param)
338 if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
340 def get_parametres_fonctions_avant_etape(self,etape):
342 Retourne deux éléments :
343 - une liste contenant les noms des paramètres (constantes ou EVAL)
345 - une liste contenant les formules définies avant etape
349 # on récupère le contexte avant etape
350 # on ne peut mettre dans les deux listes que des éléments de ce contexte
351 d=self.get_contexte_avant(etape)
352 # construction de l_constantes
353 for param in self.params:
355 if not nom : continue
356 if d.has_key(nom): l_constantes.append(nom)
357 # construction de l_fonctions
358 for form in self.fonctions:
360 if not nom : continue
361 if d.has_key(nom): l_fonctions.append(form.get_formule())
363 # on ajoute les concepts produits par DEFI_VALEUR
364 # XXX On pourrait peut etre faire plutot le test sur le type
365 # de concept : entier, reel, complexe, etc.
366 for k,v in d.items():
367 if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
368 l_constantes.append(k)
370 # on retourne les deux listes
371 return l_constantes,l_fonctions
373 def get_nb_etapes_avant(self,niveau):
375 Retourne le nombre d etapes avant le debut de niveau
378 for niv in self.etapes_niveaux:
379 if niv == niveau:break
380 nb=nb+len(niv.etapes)
383 def send_message(self,message):
385 self.appli.send_message(message)
387 def init_modif(self):
389 Méthode appelée au moment où une modification va être faite afin de
390 déclencher d'éventuels traitements pré-modification
392 self.state = 'modified'
398 def get_liste_mc_inconnus(self):
400 Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
402 # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
404 for etape in self.etapes :
406 if not etape.isvalid() :
407 l = etape.get_liste_mc_inconnus()
408 if l : l_mc.extend(l)
411 def get_genealogie(self):
413 Retourne la liste des noms des ascendants de l'objet self
414 jusqu'à la première ETAPE parent.
418 def set_etape_context(self,etape):
420 Positionne l'etape qui sera utilisee dans NommerSdProd pour
421 decider si le concept passé pourra etre nommé
423 self._etape_context=etape
425 def reset_context(self):
427 Cette methode reinitialise le contexte glissant pour pouvoir
428 tenir compte des modifications de l'utilisateur : création
429 de commandes, nommage de concepts, etc.
431 self.current_context={}
432 self.index_etape_courante=0
434 def del_sdprod(self,sd):
436 Supprime la SD sd de la liste des sd et des dictionnaires de contexte
438 if sd in self.sds : self.sds.remove(sd)
439 if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
440 if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
442 def del_param(self,param):
444 Supprime le paramètre param de la liste des paramètres
447 if param in self.params : self.params.remove(param)
448 if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
450 def del_fonction(self,fonction):
452 Supprime la fonction fonction de la liste des fonctions
455 if fonction in self.fonctions : self.fonctions.remove(fonction)
456 if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
458 def append_sdprod(self,sd):
460 Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
461 même nom n'existe pas déjà
463 if sd == None or sd.nom == None:return
465 o=self.sds_dict.get(sd.nom,None)
466 if isinstance(o,ASSD):
467 raise AsException("Nom de concept deja defini : %s" % sd.nom)
468 self.sds_dict[sd.nom]=sd
469 self.g_context[sd.nom] = sd
470 if sd not in self.sds : self.sds.append(sd)
472 def append_param(self,param):
474 Ajoute le paramètre param à la liste des params
475 et au contexte global
477 # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
478 if param not in self.params : self.params.append(param)
479 self.g_context[param.nom]=param
481 def append_fonction(self,fonction):
483 Ajoute la fonction fonction à la liste des fonctions
484 et au contexte global
486 # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
487 if fonction not in self.fonctions : self.fonctions.append(fonction)
488 self.g_context[fonction.nom]=fonction
490 def delete_concept(self,sd):
495 Mettre a jour les etapes du JDC suite à la disparition du
497 Seuls les mots cles simples MCSIMP font un traitement autre
498 que de transmettre aux fils
500 for etape in self.etapes :
501 etape.delete_concept(sd)
503 def replace_concept_after_etape(self,etape,old_sd,sd):
505 Met à jour les étapes du JDC qui sont après etape en fonction
506 du remplacement du concept sd
508 index = self.etapes.index(etape)+1
509 if index == len(self.etapes) :
510 return # etape est la dernière étape du jdc ...on ne fait rien !
511 for child in self.etapes[index:]:
512 child.replace_concept(old_sd,sd)
514 def dump_state(self):
516 print "JDC.state: ",self.state
517 for etape in self.etapes :
518 print etape.nom+".state: ",etape.state
520 def change_unit(self,unit,etape,old_unit):
521 if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
522 self.record_unit(unit,etape)
524 def record_unit(self,unit,etape):
525 """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
528 self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
530 self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
532 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
533 def register(self,etape):
535 Cette méthode ajoute etape dans la liste
536 des etapes self.etapes et retourne l identificateur d'étape
537 fourni par l appel a g_register
539 A quoi sert editmode ?
540 - Si editmode vaut 1, on est en mode edition de JDC. On cherche
541 à enregistrer une étape que l'on a créée avec eficas (en passant
542 par addentite) auquel cas on ne veut récupérer que son numéro
543 d'enregistrement et c'est addentité qui l'enregistre dans
544 self.etapes à la bonne place...
545 - Si editmode vaut 0, on est en mode relecture d'un fichier de
546 commandes et on doit enregistrer l'étape à la fin de self.etapes
547 (dans ce cas l'ordre des étapes est bien l'ordre chronologique
550 if not self.editmode:
551 self.etapes.append(etape)
554 return self.g_register(etape)
556 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
557 def NommerSdprod(self,sd,sdnom,restrict='non'):
559 Nomme la SD apres avoir verifie que le nommage est possible :
561 Si le nom est deja utilise, leve une exception
562 Met le concept créé dans le concept global g_context
564 # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
565 # Le dictionnaire g_context ne représente pas le contexte
566 # effectif avant une étape.
567 # Il faut utiliser get_contexte_avant avec indication de l'étape
569 # Cette etape est indiquee par l'attribut _etape_context qui a ete
570 # positionné préalablement par un appel à set_etape_context
572 if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
574 if self._etape_context:
575 o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
577 o=self.sds_dict.get(sdnom,None)
579 if isinstance(o,ASSD):
580 raise AsException("Nom de concept deja defini : %s" % sdnom)
582 # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
583 # Ajoute a la creation (appel de reg_sd).
584 self.sds_dict[sdnom]=sd
587 # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
588 if restrict == 'non':
589 self.g_context[sdnom]=sd
591 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
592 def delete_concept_after_etape(self,etape,sd):
594 Met à jour les étapes du JDC qui sont après etape en fonction
595 de la disparition du concept sd
597 index = self.etapes.index(etape)+1
598 if index == len(self.etapes) :
599 return # etape est la dernière étape du jdc ...on ne fait rien !
600 for child in self.etapes[index:]:
601 child.delete_concept(sd)
603 #ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer