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 get_liste_cmd(self):
420 Retourne la liste des commandes du catalogue
422 return self.niveau.definition.get_liste_cmd()
424 def get_groups(self):
426 Retourne la liste des groupes
428 return self.niveau.definition.liste_groupes,self.niveau.definition.dict_groupes
430 def set_etape_context(self,etape):
432 Positionne l'etape qui sera utilisee dans NommerSdProd pour
433 decider si le concept passé pourra etre nommé
435 self._etape_context=etape
437 def reset_context(self):
439 Cette methode reinitialise le contexte glissant pour pouvoir
440 tenir compte des modifications de l'utilisateur : création
441 de commandes, nommage de concepts, etc.
443 self.current_context={}
444 self.index_etape_courante=0
446 def del_sdprod(self,sd):
448 Supprime la SD sd de la liste des sd et des dictionnaires de contexte
450 if sd in self.sds : self.sds.remove(sd)
451 if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
452 if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
454 def del_param(self,param):
456 Supprime le paramètre param de la liste des paramètres
459 if param in self.params : self.params.remove(param)
460 if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
462 def del_fonction(self,fonction):
464 Supprime la fonction fonction de la liste des fonctions
467 if fonction in self.fonctions : self.fonctions.remove(fonction)
468 if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
470 def append_sdprod(self,sd):
472 Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
473 même nom n'existe pas déjà
475 if sd == None or sd.nom == None:return
477 o=self.sds_dict.get(sd.nom,None)
478 if isinstance(o,ASSD):
479 raise AsException("Nom de concept deja defini : %s" % sd.nom)
480 self.sds_dict[sd.nom]=sd
481 self.g_context[sd.nom] = sd
482 if sd not in self.sds : self.sds.append(sd)
484 def append_param(self,param):
486 Ajoute le paramètre param à la liste des params
487 et au contexte global
489 # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
490 if param not in self.params : self.params.append(param)
491 self.g_context[param.nom]=param
493 def append_fonction(self,fonction):
495 Ajoute la fonction fonction à la liste des fonctions
496 et au contexte global
498 # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
499 if fonction not in self.fonctions : self.fonctions.append(fonction)
500 self.g_context[fonction.nom]=fonction
502 def delete_concept(self,sd):
507 Mettre a jour les etapes du JDC suite à la disparition du
509 Seuls les mots cles simples MCSIMP font un traitement autre
510 que de transmettre aux fils
512 for etape in self.etapes :
513 etape.delete_concept(sd)
515 def replace_concept_after_etape(self,etape,old_sd,sd):
517 Met à jour les étapes du JDC qui sont après etape en fonction
518 du remplacement du concept sd
520 index = self.etapes.index(etape)+1
521 if index == len(self.etapes) :
522 return # etape est la dernière étape du jdc ...on ne fait rien !
523 for child in self.etapes[index:]:
524 child.replace_concept(old_sd,sd)
526 def dump_state(self):
528 print "JDC.state: ",self.state
529 for etape in self.etapes :
530 print etape.nom+".state: ",etape.state
532 def change_unit(self,unit,etape,old_unit):
533 #print "change_unit",unit,etape,old_unit
534 #print id(self.recorded_units),self.recorded_units
535 #if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
536 self.record_unit(unit,etape)
538 def record_unit(self,unit,etape):
539 """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
540 #print "record_unit",unit,etape
543 self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
545 self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
546 #print id(self.recorded_units),self.recorded_units
547 #print self.recorded_units.get(None,(None,"",{}))[2]
548 #print self.recorded_units.get(None,(None,"",{}))[2].get(None,(None,"",{}))
550 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
551 def register(self,etape):
553 Cette méthode ajoute etape dans la liste
554 des etapes self.etapes et retourne l identificateur d'étape
555 fourni par l appel a g_register
557 A quoi sert editmode ?
558 - Si editmode vaut 1, on est en mode edition de JDC. On cherche
559 à enregistrer une étape que l'on a créée avec eficas (en passant
560 par addentite) auquel cas on ne veut récupérer que son numéro
561 d'enregistrement et c'est addentité qui l'enregistre dans
562 self.etapes à la bonne place...
563 - Si editmode vaut 0, on est en mode relecture d'un fichier de
564 commandes et on doit enregistrer l'étape à la fin de self.etapes
565 (dans ce cas l'ordre des étapes est bien l'ordre chronologique
568 if not self.editmode:
569 self.etapes.append(etape)
572 return self.g_register(etape)
574 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
575 def NommerSdprod(self,sd,sdnom,restrict='non'):
577 Nomme la SD apres avoir verifie que le nommage est possible :
579 Si le nom est deja utilise, leve une exception
580 Met le concept créé dans le concept global g_context
582 # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
583 # Le dictionnaire g_context ne représente pas le contexte
584 # effectif avant une étape.
585 # Il faut utiliser get_contexte_avant avec indication de l'étape
587 # Cette etape est indiquee par l'attribut _etape_context qui a ete
588 # positionné préalablement par un appel à set_etape_context
590 if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
592 if self._etape_context:
593 o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
595 o=self.sds_dict.get(sdnom,None)
597 if isinstance(o,ASSD):
598 raise AsException("Nom de concept deja defini : %s" % sdnom)
600 # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
601 # Ajoute a la creation (appel de reg_sd).
602 self.sds_dict[sdnom]=sd
605 # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
606 if restrict == 'non':
607 self.g_context[sdnom]=sd
609 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
610 def delete_concept_after_etape(self,etape,sd):
612 Met à jour les étapes du JDC qui sont après etape en fonction
613 de la disparition du concept sd
615 index = self.etapes.index(etape)+1
616 if index == len(self.etapes) :
617 return # etape est la dernière étape du jdc ...on ne fait rien !
618 for child in self.etapes[index:]:
619 child.delete_concept(sd)
621 #ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer