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)
105 elif name == "PARAMETRE":
106 # ajout d'un parametre
107 self.set_current_step()
108 nom_param = '_param_'+str(len(self.params)+1)
109 objet = parametre.PARAMETRE(nom=nom_param)
110 if pos == None : pos = 0
111 self.etapes.insert(pos,objet)
117 elif name == "PARAMETRE_EVAL":
118 # ajout d'un parametre EVAL
119 self.set_current_step()
120 nom_param = '_param_'+str(len(self.params)+1)
121 objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
122 if pos == None : pos = 0
123 self.etapes.insert(pos,objet)
129 elif type(name)==types.InstanceType:
130 # on est dans le cas où on veut ajouter une commande déjà
131 # existante (par copie donc)
132 # on est donc nécessairement en mode editeur ...
134 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
136 self.set_current_step()
137 if isinstance(objet,ETAPE):
138 if objet.nom_niveau_definition == 'JDC':
139 # l'objet dépend directement du JDC
142 # l'étape dépend d'un niveau et non directement du JDC :
143 # il faut l'enregistrer dans le niveau de parent
144 objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
145 objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
146 self.etapes.insert(pos,objet)
147 # il faut vérifier que les concepts utilisés par objet existent bien
148 # à ce niveau d'arborescence
149 objet.verif_existence_sd()
153 print "addentite",self.etapes
157 # On veut ajouter une nouvelle commande
159 self.set_current_step()
160 cmd=self.get_cmd(name)
161 # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
162 # auprès du step courant car editmode vaut 1
163 # Par contre elle a le bon parent grace a set_current_step
165 if pos == None : pos = 0
166 self.etapes.insert(pos,e)
167 self.reset_current_step()
171 print "addentite",self.etapes
174 except AsException,e:
175 self.reset_current_step()
177 raise AsException("Impossible d ajouter la commande "+name + '\n' +str(e))
179 traceback.print_exc()
180 self.reset_current_step()
182 raise AsException("Impossible d ajouter la commande "+name)
184 def set_current_step(self):
185 CONTEXT.unset_current_step()
186 CONTEXT.set_current_step(self)
188 def reset_current_step(self):
189 CONTEXT.unset_current_step()
191 def liste_mc_presents(self):
194 def get_sd_avant_etape(self,nom_sd,etape):
195 return self.get_contexte_avant(etape).get(nom_sd,None)
197 def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
199 Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement
200 définie apres etape en tenant compte des concepts detruits
201 Si avec vaut 'non' exclut etape de la recherche
203 ietap=self.etapes.index(etape)
204 if avec == 'non':ietap=ietap+1
206 for e in self.etapes[ietap:]:
209 autre_sd=d.get(nom_sd,None)
211 # Le concept a ete detruit
213 if autre_sd is not sd :
214 # L'etape produit un concept de meme nom
215 if hasattr(e,'reuse') and e.reuse == autre_sd:
216 # Le concept etant reutilise, on interrompt la recherche.
217 # On considere qu'il n'y a pas de nouveau concept defini
218 # meme si dans les etapes suivantes le concept est detruit
219 # et un concept de meme nom créé.
222 # Le concept est produit par l'etape
224 # On n'a rien trouve. Pas de concept de nom nom_sd
227 def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
229 Cette méthode retourne la SD de nom nom_sd qui est éventuellement
231 Si avec vaut 'non' exclut etape de la recherche
233 ietap=self.etapes.index(etape)
234 if avec == 'non':ietap=ietap+1
235 for e in self.etapes[ietap:]:
236 sd=e.get_sdprods(nom_sd)
238 if hasattr(e,'reuse'):
243 def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
245 Fonction: retourne la SD de nom nom_sd qui est éventuellement
246 définie avant ou apres etape
247 Permet de vérifier si un concept de meme nom existe dans le périmètre
249 Si avec vaut 'non' exclut etape de la recherche
251 sd=self.get_sd_avant_etape(nom_sd,etape)
253 return self.get_sd_apres_etape(nom_sd,etape,avec)
255 def get_contexte_apres(self,etape):
257 Retourne le dictionnaire des concepts connus apres etape
258 On tient compte des commandes qui modifient le contexte
259 comme DETRUIRE ou les macros
260 Si etape == None, on retourne le contexte en fin de JDC
262 if not etape: return self.get_contexte_avant(etape)
264 d=self.get_contexte_avant(etape)
265 if etape.isactif():etape.update_context(d)
266 self.index_etape_courante=self.index_etape_courante+1
269 def active_etapes(self):
271 Cette méthode a pour fonction de désactiver les étapes qui doivent
272 l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas
273 comprises entre le premier DEBUT/POURSUITE et le premier FIN
274 et rendre actives les autres
276 if self.definition.code == 'ASTER' :
277 # Seulement pour ASTER :
278 # Avant DEBUT actif vaut 0
279 # Apres DEBUT et avant le 1er FIN actif vaut 1
280 # Apres le 1er FIN actif vaut -1
284 for etape in self.etapes:
285 if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
290 if etape.nom == 'FIN':actif=-1
292 def suppentite(self,etape) :
294 Cette methode a pour fonction de supprimer une étape dans
296 Retourne 1 si la suppression a pu être effectuée,
297 Retourne 0 dans le cas contraire
300 # On memorise le contexte avant l'etape a supprimer
301 d=self.get_contexte_avant(etape)
302 index_etape=self.etapes.index(etape)
304 self.etapes.remove(etape)
305 if etape.niveau is not self:
306 # Dans ce cas l'étape est enregistrée dans un niveau
307 # Il faut la désenregistrer
308 etape.niveau.unregister(etape)
309 etape.supprime_sdprods()
312 # Apres suppression de l'etape il faut controler que les etapes
313 # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
314 for e in self.etapes[index_etape:]:
323 if not self.cr.estvide():return
327 def register_parametre(self,param):
329 Cette méthode sert à ajouter un paramètre dans la liste des paramètres
331 self.params.append(param)
333 def register_fonction(self,fonction):
335 Cette méthode sert à ajouter une fonction dans la liste des fonctions
337 self.fonctions.append(fonction)
339 def delete_param(self,param):
341 Supprime le paramètre param de la liste des paramètres
344 if param in self.params : self.params.remove(param)
345 if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
347 def get_parametres_fonctions_avant_etape(self,etape):
349 Retourne deux éléments :
350 - une liste contenant les noms des paramètres (constantes ou EVAL)
352 - une liste contenant les formules définies avant etape
356 # on récupère le contexte avant etape
357 # on ne peut mettre dans les deux listes que des éléments de ce contexte
358 d=self.get_contexte_avant(etape)
359 # construction de l_constantes
360 for param in self.params:
362 if not nom : continue
363 if d.has_key(nom): l_constantes.append(nom)
364 # construction de l_fonctions
365 for form in self.fonctions:
367 if not nom : continue
368 if d.has_key(nom): l_fonctions.append(form.get_formule())
370 # on ajoute les concepts produits par DEFI_VALEUR
371 # XXX On pourrait peut etre faire plutot le test sur le type
372 # de concept : entier, reel, complexe, etc.
373 for k,v in d.items():
374 if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
375 l_constantes.append(k)
377 # on retourne les deux listes
378 return l_constantes,l_fonctions
380 def get_nb_etapes_avant(self,niveau):
382 Retourne le nombre d etapes avant le debut de niveau
385 for niv in self.etapes_niveaux:
386 if niv == niveau:break
387 nb=nb+len(niv.etapes)
390 def send_message(self,message):
392 self.appli.send_message(message)
394 def init_modif(self):
396 Méthode appelée au moment où une modification va être faite afin de
397 déclencher d'éventuels traitements pré-modification
399 print "init_modif",self
400 self.state = 'modified'
403 print "fin_modif",self
407 def get_liste_mc_inconnus(self):
409 Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
411 # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
413 for etape in self.etapes :
415 if not etape.isvalid() :
416 l = etape.get_liste_mc_inconnus()
417 if l : l_mc.extend(l)
420 def get_genealogie(self):
422 Retourne la liste des noms des ascendants de l'objet self
423 jusqu'à la première ETAPE parent.
427 def get_liste_cmd(self):
429 Retourne la liste des commandes du catalogue
431 return self.niveau.definition.get_liste_cmd()
433 def get_groups(self):
435 Retourne la liste des groupes
437 return self.niveau.definition.liste_groupes,self.niveau.definition.dict_groupes
439 def set_etape_context(self,etape):
441 Positionne l'etape qui sera utilisee dans NommerSdProd pour
442 decider si le concept passé pourra etre nommé
444 self._etape_context=etape
446 def reset_context(self):
448 Cette methode reinitialise le contexte glissant pour pouvoir
449 tenir compte des modifications de l'utilisateur : création
450 de commandes, nommage de concepts, etc.
452 self.current_context={}
453 self.index_etape_courante=0
455 def del_sdprod(self,sd):
457 Supprime la SD sd de la liste des sd et des dictionnaires de contexte
459 if sd in self.sds : self.sds.remove(sd)
460 if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
461 if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
463 def del_param(self,param):
465 Supprime le paramètre param de la liste des paramètres
468 if param in self.params : self.params.remove(param)
469 if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
471 def del_fonction(self,fonction):
473 Supprime la fonction fonction de la liste des fonctions
476 if fonction in self.fonctions : self.fonctions.remove(fonction)
477 if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
479 def append_sdprod(self,sd):
481 Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
482 même nom n'existe pas déjà
484 if sd == None or sd.nom == None:return
486 o=self.sds_dict.get(sd.nom,None)
487 if isinstance(o,ASSD):
488 raise AsException("Nom de concept deja defini : %s" % sd.nom)
489 self.sds_dict[sd.nom]=sd
490 self.g_context[sd.nom] = sd
491 if sd not in self.sds : self.sds.append(sd)
493 def append_param(self,param):
495 Ajoute le paramètre param à la liste des params
496 et au contexte global
498 # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
499 if param not in self.params : self.params.append(param)
500 self.g_context[param.nom]=param
502 def append_fonction(self,fonction):
504 Ajoute la fonction fonction à la liste des fonctions
505 et au contexte global
507 # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
508 if fonction not in self.fonctions : self.fonctions.append(fonction)
509 self.g_context[fonction.nom]=fonction
511 def delete_concept(self,sd):
516 Mettre a jour les etapes du JDC suite à la disparition du
518 Seuls les mots cles simples MCSIMP font un traitement autre
519 que de transmettre aux fils
521 for etape in self.etapes :
522 etape.delete_concept(sd)
524 def replace_concept_after_etape(self,etape,old_sd,sd):
526 Met à jour les étapes du JDC qui sont après etape en fonction
527 du remplacement du concept sd
529 index = self.etapes.index(etape)+1
530 if index == len(self.etapes) :
531 return # etape est la dernière étape du jdc ...on ne fait rien !
532 for child in self.etapes[index:]:
533 child.replace_concept(old_sd,sd)
535 def dump_state(self):
537 print "JDC.state: ",self.state
538 for etape in self.etapes :
539 print etape.nom+".state: ",etape.state
541 def change_unit(self,unit,etape,old_unit):
542 #print "change_unit",unit,etape,old_unit
543 #print id(self.recorded_units),self.recorded_units
544 #if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
545 self.record_unit(unit,etape)
547 def record_unit(self,unit,etape):
548 """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
549 #print "record_unit",unit,etape
552 self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
554 self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
555 #print id(self.recorded_units),self.recorded_units
556 #print self.recorded_units.get(None,(None,"",{}))[2]
557 #print self.recorded_units.get(None,(None,"",{}))[2].get(None,(None,"",{}))
559 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
560 def register(self,etape):
562 Cette méthode ajoute etape dans la liste
563 des etapes self.etapes et retourne l identificateur d'étape
564 fourni par l appel a g_register
566 A quoi sert editmode ?
567 - Si editmode vaut 1, on est en mode edition de JDC. On cherche
568 à enregistrer une étape que l'on a créée avec eficas (en passant
569 par addentite) auquel cas on ne veut récupérer que son numéro
570 d'enregistrement et c'est addentité qui l'enregistre dans
571 self.etapes à la bonne place...
572 - Si editmode vaut 0, on est en mode relecture d'un fichier de
573 commandes et on doit enregistrer l'étape à la fin de self.etapes
574 (dans ce cas l'ordre des étapes est bien l'ordre chronologique
577 if not self.editmode:
578 self.etapes.append(etape)
581 return self.g_register(etape)
583 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
584 def NommerSdprod(self,sd,sdnom,restrict='non'):
586 Nomme la SD apres avoir verifie que le nommage est possible :
588 Si le nom est deja utilise, leve une exception
589 Met le concept créé dans le concept global g_context
591 # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
592 # Le dictionnaire g_context ne représente pas le contexte
593 # effectif avant une étape.
594 # Il faut utiliser get_contexte_avant avec indication de l'étape
596 # Cette etape est indiquee par l'attribut _etape_context qui a ete
597 # positionné préalablement par un appel à set_etape_context
599 if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
601 if self._etape_context:
602 o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
604 o=self.sds_dict.get(sdnom,None)
606 if isinstance(o,ASSD):
607 raise AsException("Nom de concept deja defini : %s" % sdnom)
609 # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
610 # Ajoute a la creation (appel de reg_sd).
611 self.sds_dict[sdnom]=sd
614 # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
615 if restrict == 'non':
616 self.g_context[sdnom]=sd
618 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
619 def delete_concept_after_etape(self,etape,sd):
621 Met à jour les étapes du JDC qui sont après etape en fonction
622 de la disparition du concept sd
624 index = self.etapes.index(etape)+1
625 if index == len(self.etapes) :
626 return # etape est la dernière étape du jdc ...on ne fait rien !
627 for child in self.etapes[index:]:
628 child.delete_concept(sd)
630 #ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer