Salome HOME
11379dd87de61cf53dd79e79df21becee445233d
[tools/eficas.git] / Ihm / I_JDC.py
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.
9 #
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.
14 #
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.
18 #
19 #
20 # ======================================================================
21 """
22 """
23 # Modules Python
24 import types,traceback,sys,os
25 import string,linecache
26
27 # Modules Eficas
28 import I_OBJECT
29 import Noyau
30 from Noyau.N_ASSD import ASSD
31 #from Noyau.N_LASSD import LASSD
32 from Noyau.N_ETAPE import ETAPE
33 from Noyau.N_Exception import AsException
34 from Extensions import commentaire,parametre,parametre_eval
35 import CONNECTOR
36 import Validation
37
38 class LASSD:
39    pass
40
41 class JDC(I_OBJECT.OBJECT):
42    """
43    """
44    def __init__(self):
45       self.editmode=0
46       self.etapes_niveaux=[]
47       self.niveau=self
48       self.params=[]
49       self.fonctions=[]
50       self._etape_context=None
51       self.recorded_units={}
52       self.old_recorded_units={}
53
54    def get_index(self,objet):
55       """
56         Retourne la position d'objet dans la liste self
57       """
58       return self.etapes.index(objet)
59
60    def get_sd_avant_du_bon_type(self,etape,types_permis):
61       """
62           Retourne la liste des concepts avant etape d'un type acceptable
63       """
64       d=self.get_contexte_avant(etape)
65       l=[]
66       for k,v in d.items():
67         if type(v) != types.InstanceType and not isinstance(v,object): continue
68         # On considère que seul assd indique un type quelconque pas CO
69         elif self.assd in types_permis :
70            l.append(k)
71         elif self.est_permis(v,types_permis):
72            l.append(k)
73       l.sort()
74       return l
75
76    def get_sd_avant_du_bon_type_pour_type_de_base(self,etape,type):
77       """
78           Retourne la liste des concepts avant etape d'1 type de base acceptable
79           Attention different de la routine précédente : 1 seul type passé en parametre
80           Teste sur issubclass et par sur le type permis
81       """
82       d=self.get_contexte_avant(etape)
83       l=[]
84       try :
85          typeverif=self.cata[0].__dict__[type]
86       except :
87          return l
88       for k,v in d.items():
89         if issubclass(v.__class__,typeverif): 
90            l.append(k)
91       l.sort()
92       return l
93
94    def cherche_list_avant(self,etape,valeur):
95        d=self.get_contexte_avant(etape)
96        for k,v in d.items():
97           if issubclass(v.__class__,LASSD):
98              if k == valeur :
99                 return k
100         # Attention pour enlever les . a la fin des pretendus reels
101              if k == valeur[0:-1] :
102                 return v
103        return None
104
105    def est_permis(self,v,types_permis):
106       for type_ok in types_permis:
107           if type_ok in ('R','I','C','TXM') and v in self.params : 
108              return 1
109           elif type_ok == 'R' and v.__class__.__name__ == 'reel' : 
110              return 1
111           elif type_ok == 'I' and v.__class__.__name__ == 'entier' : 
112              return 1
113           elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : 
114              return 1
115           elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : 
116              return 1
117           elif type(type_ok) != types.ClassType and not isinstance(type_ok,type): 
118              continue
119           elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
120              return 1
121       return 0
122
123    def addentite(self,name,pos):
124       """
125           Ajoute une entite :
126           Si name est le nom d une commande ou un commentaire ajoute 
127           une etape au JDC
128           Sinon remonte une erreur
129       """
130       self.init_modif()
131       self.editmode=1
132       if name == "COMMENTAIRE" :
133         # ajout d'un commentaire
134         self.set_current_step()
135         ind = 1
136         for child in self.etapes :
137           if isinstance(child,commentaire.COMMENTAIRE):
138             ind = ind+1
139         objet = commentaire.COMMENTAIRE('',parent=self)
140         objet.nom = "_comm_"+`ind`
141         if pos == None : pos = 0
142         self.etapes.insert(pos,objet)
143         self.editmode=0
144         self.active_etapes()
145         CONNECTOR.Emit(self,"add",objet)
146         self.fin_modif()
147         return objet
148       elif name == "PARAMETRE":
149         # ajout d'un parametre
150         self.set_current_step()
151         nom_param = '_param_'+str(len(self.params)+1)
152         objet = parametre.PARAMETRE(nom=nom_param)
153         if pos == None : pos = 0
154         self.etapes.insert(pos,objet)
155         self.editmode=0
156         self.reset_context()
157         self.active_etapes()
158         CONNECTOR.Emit(self,"add",objet)
159         self.fin_modif()
160         return objet
161       elif name == "PARAMETRE_EVAL":
162         # ajout d'un parametre EVAL
163         self.set_current_step()
164         nom_param = '_param_'+str(len(self.params)+1)
165         objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
166         if pos == None : pos = 0
167         self.etapes.insert(pos,objet)
168         self.editmode=0
169         self.reset_context()
170         self.active_etapes()
171         CONNECTOR.Emit(self,"add",objet)
172         self.fin_modif()
173         return objet
174       elif type(name)==types.InstanceType:
175         # on est dans le cas où on veut ajouter une commande déjà 
176         # existante (par copie donc)
177         # on est donc nécessairement en mode editeur ...
178         objet = name
179         # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
180         objet.reparent(self)
181         self.set_current_step()
182         if isinstance(objet,ETAPE):
183           if objet.nom_niveau_definition == 'JDC':
184             # l'objet dépend directement du JDC
185             objet.niveau = self
186           else:
187             # l'étape dépend d'un niveau et non directement du JDC :
188             # il faut l'enregistrer dans le niveau de parent
189             objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
190             objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
191         self.etapes.insert(pos,objet)
192         # il faut vérifier que les concepts utilisés par objet existent bien
193         # à ce niveau d'arborescence
194         objet.verif_existence_sd()
195         objet.update_mc_global()
196         self.active_etapes()
197         self.editmode=0
198         self.reset_context()
199         CONNECTOR.Emit(self,"add",objet)
200         self.fin_modif()
201         return objet
202       else :
203         # On veut ajouter une nouvelle commande
204         try:
205           self.set_current_step()
206           cmd=self.get_cmd(name)
207           # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
208           # auprès du step courant car editmode vaut 1
209           # Par contre elle a le bon parent grace a set_current_step
210           e=cmd.make_objet()
211           if pos == None : pos = 0
212           self.etapes.insert(pos,e)
213           self.reset_current_step()
214           self.editmode=0
215           self.reset_context()
216           self.active_etapes()
217           CONNECTOR.Emit(self,"add",e)
218           self.fin_modif()
219           return e
220         except AsException,e:
221           self.reset_current_step()
222           self.editmode=0
223           raise AsException("Impossible d ajouter la commande "+name + '\n' +str(e))
224         except:
225           traceback.print_exc()
226           self.reset_current_step()
227           self.editmode=0
228           raise AsException("Impossible d ajouter la commande "+name)
229
230    def close(self):
231       #print "JDC.close",self
232       for etape in self.etapes:
233           if hasattr(etape,"close"):etape.close()
234       CONNECTOR.Emit(self,"close")
235
236    def set_current_step(self):
237       CONTEXT.unset_current_step()
238       CONTEXT.set_current_step(self)
239
240    def reset_current_step(self):
241       CONTEXT.unset_current_step()
242
243    def liste_mc_presents(self):
244       return []
245
246    def get_sd_avant_etape(self,nom_sd,etape):
247       return self.get_contexte_avant(etape).get(nom_sd,None)
248
249    def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
250       """ 
251            Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement
252            définie apres etape en tenant compte des concepts detruits
253            Si avec vaut 'non' exclut etape de la recherche
254       """
255       #print "JDC.get_sd_apres_etape_avec_detruire",nom_sd,sd
256       ietap=self.etapes.index(etape)
257       if avec == 'non':ietap=ietap+1
258       d={nom_sd:sd}
259       for e in self.etapes[ietap:]:
260          if e.isactif():
261             e.update_context(d)
262             autre_sd=d.get(nom_sd,None)
263             if autre_sd is None:
264               # Le concept a ete detruit. On interrompt la recherche car il n'y a
265               # pas eu de redefinition du concept (il n'y a pas de conflit potentiel).
266               return None
267             if autre_sd is not sd :
268               # L'etape produit un concept different de meme nom. La situation n'est
269               # pas saine (sauf peut etre si reuse ???)
270               if hasattr(e,'reuse') and e.reuse == autre_sd:
271                  # Le concept etant reutilise, on interrompt la recherche. 
272                  # On considere qu'il n'y a pas de nouveau concept defini
273                  # meme si dans les etapes suivantes le concept est detruit
274                  # et un concept de meme nom créé.
275                  # AVERIFIER : avec reuse le concept devrait etre le meme
276                  # le passage par ici est tres improbable
277                  return None
278               else:
279                  # Le concept est produit par l'etape (Il y a conflit potentiel).
280                  # Le concept est redefini par une etape posterieure.
281                  return autre_sd
282       # Pas de destruction du concept ni de redefinition. On retourne le
283       # concept initial
284       return sd
285
286    def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
287       """ 
288            Cette méthode retourne la SD de nom nom_sd qui est éventuellement
289            définie apres etape 
290            Si avec vaut 'non' exclut etape de la recherche
291       """
292       ietap=self.etapes.index(etape)
293       if avec == 'non':ietap=ietap+1
294       for e in self.etapes[ietap:]:
295         sd=e.get_sdprods(nom_sd)
296         if sd:
297           if hasattr(e,'reuse'):
298             if e.reuse != sd:
299               return sd
300       return None
301
302    def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
303       """
304            Fonction: retourne la SD de nom nom_sd qui est éventuellement
305            définie avant ou apres etape
306            Permet de vérifier si un concept de meme nom existe dans le périmètre 
307            d'une étape
308            Si avec vaut 'non' exclut etape de la recherche
309       """
310       sd=self.get_sd_avant_etape(nom_sd,etape)
311       if sd:return sd
312       return self.get_sd_apres_etape(nom_sd,etape,avec)
313
314    def get_contexte_apres(self,etape):
315       """
316          Retourne le dictionnaire des concepts connus apres etape
317          On tient compte des commandes qui modifient le contexte
318          comme DETRUIRE ou les macros
319          Si etape == None, on retourne le contexte en fin de JDC
320       """
321       if not etape: return self.get_contexte_avant(etape)
322
323       d=self.get_contexte_avant(etape)
324       if etape.isactif():etape.update_context(d)
325       self.index_etape_courante=self.index_etape_courante+1
326       return d
327
328    def active_etapes(self):
329       """
330           Cette méthode a pour fonction de désactiver les étapes qui doivent
331           l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas 
332           comprises entre le premier DEBUT/POURSUITE et le premier FIN 
333           et rendre actives les autres
334       """
335       if self.definition.code == 'ASTER' :
336          # Seulement pour ASTER :
337          # Avant DEBUT actif vaut 0
338          # Apres DEBUT et avant le 1er FIN actif vaut 1
339          # Apres le 1er FIN actif vaut -1
340          actif=0
341       else:
342          actif=1
343       for etape in self.etapes:
344         if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
345         if actif == 1:
346            etape.active()
347         else:
348            etape.inactive()
349         if etape.nom == 'FIN':actif=-1
350
351    def suppentite(self,etape) :
352       """  
353           Cette methode a pour fonction de supprimer une étape dans 
354           un jeu de commandes
355           Retourne 1 si la suppression a pu être effectuée,
356           Retourne 0 dans le cas contraire
357       """
358       #print "suppentite",self
359       #PN correction de bugs 
360       if etape not in self.etapes:
361          return 0
362
363       self.init_modif()
364       index_etape=self.etapes.index(etape)
365       self.etapes.remove(etape)
366
367       if etape.niveau is not self:
368         # Dans ce cas l'étape est enregistrée dans un niveau
369         # Il faut la désenregistrer
370         etape.niveau.unregister(etape)
371
372       etape.supprime_sdprods()
373       etape.close()
374       etape.supprime()
375       self.active_etapes()
376
377       # Apres suppression de l'etape il faut controler que les etapes
378       # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
379       if index_etape > 0: 
380          index_etape=index_etape-1
381          etape=self.etapes[index_etape]
382       else:
383          etape=None
384       self.control_context_apres(etape)
385       
386       self.reset_context()
387       CONNECTOR.Emit(self,"supp",etape)
388       self.fin_modif()
389       return 1
390
391    def control_context_apres(self,etape):
392       """
393          Cette méthode verifie que les etapes apres l'etape etape
394          ont bien des concepts produits acceptables (pas de conflit de 
395          nom principalement)
396          Si des concepts produits ne sont pas acceptables ils sont supprimés.
397          Effectue les verifications sur les etapes du jdc mais aussi sur les
398          jdc parents s'ils existent.
399       """
400       #print "control_context_apres",self,etape
401       #Regularise les etapes du jdc apres l'etape etape
402       self.control_jdc_context_apres(etape)
403
404    def control_jdc_context_apres(self,etape):
405       """
406           Methode semblable a control_context_apres mais ne travaille
407           que sur les etapes et sous etapes du jdc
408       """
409       #print "control_jdc_context_apres",self,etape
410       if etape is None:
411          # on demarre de la premiere etape
412          index_etape=0
413       else:
414          index_etape=self.etapes.index(etape)+1
415
416       try:
417          etape=self.etapes[index_etape]
418       except:
419          #derniere etape du jdc : rien a faire
420          return
421
422       context=self.get_contexte_avant(etape)
423
424       for e in self.etapes[index_etape:]:
425           e.control_sdprods(context)
426           e.update_context(context)
427
428    def analyse(self):
429       self.compile()
430       if not self.cr.estvide():return
431       self.exec_compile()
432       self.active_etapes()
433
434    def register_parametre(self,param):
435       """
436           Cette méthode sert à ajouter un paramètre dans la liste des paramètres
437       """
438       self.params.append(param)
439
440    def register_fonction(self,fonction):
441       """
442           Cette méthode sert à ajouter une fonction dans la liste des fonctions
443       """
444       self.fonctions.append(fonction)
445
446    def delete_param(self,param):
447       """
448           Supprime le paramètre param de la liste des paramètres
449           et du contexte gobal
450       """
451       if param in self.params : self.params.remove(param)
452       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
453
454    def get_parametres_fonctions_avant_etape(self,etape):
455       """
456           Retourne deux éléments :
457           - une liste contenant les noms des paramètres (constantes ou EVAL) 
458             définis avant etape
459           - une liste contenant les formules définies avant etape
460       """
461       l_constantes = []
462       l_fonctions = []
463       # on récupère le contexte avant etape
464       # on ne peut mettre dans les deux listes que des éléments de ce contexte
465       d=self.get_contexte_avant(etape)
466       # construction de l_constantes
467       for param in self.params:
468         nom = param.nom
469         if not nom : continue
470         if d.has_key(nom): l_constantes.append(nom)
471       # construction de l_fonctions
472       for form in self.fonctions:
473         nom = form.nom
474         if not nom : continue
475         if d.has_key(nom): l_fonctions.append(form.get_formule())
476
477       # on ajoute les concepts produits par DEFI_VALEUR
478       # XXX On pourrait peut etre faire plutot le test sur le type
479       # de concept : entier, reel, complexe, etc.
480       for k,v in d.items():
481          if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
482             l_constantes.append(k)
483
484       # on retourne les deux listes
485       return l_constantes,l_fonctions
486
487    def get_nb_etapes_avant(self,niveau):
488       """ 
489           Retourne le nombre d etapes avant le debut de niveau
490       """
491       nb=0
492       for niv in self.etapes_niveaux:
493         if niv == niveau:break
494         nb=nb+len(niv.etapes)
495       return nb
496
497    def send_message(self,message):
498       if self.appli:
499          self.appli.send_message(message)
500
501    def init_modif(self):
502       """
503       Méthode appelée au moment où une modification va être faite afin de 
504       déclencher d'éventuels traitements pré-modification
505       """
506       #print "init_modif",self
507       self.state = 'modified'
508
509    def fin_modif(self):
510       #print "fin_modif",self
511       CONNECTOR.Emit(self,"valid")
512       self.isvalid()
513       pass
514
515    def deep_update_condition_bloc(self):
516       # pour le moment, on ne fait rien
517       raise "Not implemented"
518
519    def update_condition_bloc(self):
520       # pour le moment, on ne fait rien
521       raise "Not implemented"
522
523    def get_liste_mc_inconnus(self):
524      """
525      Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
526      """
527      # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
528      l_mc = []
529      for etape in self.etapes :
530          if etape.isactif() :
531             if not etape.isvalid() :
532                l = etape.get_liste_mc_inconnus()
533                if l : l_mc.extend(l)
534      return l_mc    
535
536    def get_genealogie(self):
537       """
538           Retourne la liste des noms des ascendants de l'objet self
539           jusqu'à la première ETAPE parent.
540       """
541       return []
542
543    def get_liste_cmd(self):
544       """
545           Retourne la liste des commandes du catalogue
546       """
547       return self.niveau.definition.get_liste_cmd()
548
549    def get_groups(self):
550       """
551           Retourne la liste des groupes
552       """
553       return self.niveau.definition.liste_groupes,self.niveau.definition.dict_groupes
554
555    def set_etape_context(self,etape):
556       """
557           Positionne l'etape qui sera utilisee dans NommerSdProd pour
558           decider si le concept passé pourra etre  nommé
559       """
560       self._etape_context=etape
561
562    def reset_context(self):
563       """ 
564           Cette methode reinitialise le contexte glissant pour pouvoir
565           tenir compte des modifications de l'utilisateur : création
566           de commandes, nommage de concepts, etc.
567       """
568       #print "reset_context",self,self.nom
569       self.current_context={}
570       self.index_etape_courante=0
571    #   for etape in self.etapes:
572    #       etape.reset_context()
573
574    def del_sdprod(self,sd):
575       """
576           Supprime la SD sd de la liste des sd et des dictionnaires de contexte
577       """
578       #print "del_sdprod",self,sd
579       #print "del_sdprod",self.sds
580       #print "del_sdprod",self.g_context
581       #print "del_sdprod",self.sds_dict
582       if sd in self.sds : self.sds.remove(sd)
583       if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
584       if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
585
586    def del_param(self,param):
587       """
588           Supprime le paramètre param de la liste des paramètres
589           et du contexte gobal
590       """
591       if param in self.params : self.params.remove(param)
592       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
593
594    def del_fonction(self,fonction):
595       """
596           Supprime la fonction fonction de la liste des fonctions
597           et du contexte gobal
598       """
599       if fonction in self.fonctions : self.fonctions.remove(fonction)
600       if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
601
602    def append_sdprod(self,sd):
603       """
604           Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
605           même nom n'existe pas déjà
606       """
607       if sd == None or sd.nom == None:return
608
609       o=self.sds_dict.get(sd.nom,None)
610       if isinstance(o,ASSD):
611          raise AsException("Nom de concept deja defini : %s" % sd.nom)
612       self.sds_dict[sd.nom]=sd
613       self.g_context[sd.nom] = sd
614       if sd not in self.sds : self.sds.append(sd)
615
616    def append_param(self,param):
617       """
618           Ajoute le paramètre param à la liste des params
619           et au contexte global
620       """
621       # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
622       if param not in self.params : self.params.append(param)
623       self.g_context[param.nom]=param
624
625    def append_fonction(self,fonction):
626       """
627           Ajoute la fonction fonction à la liste des fonctions
628           et au contexte global
629       """
630       # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
631       if fonction not in self.fonctions : self.fonctions.append(fonction)
632       self.g_context[fonction.nom]=fonction
633
634    def delete_concept(self,sd):
635       """
636           Inputs :
637              - sd=concept detruit
638           Fonction :
639           Mettre a jour les etapes du JDC suite à la disparition du
640           concept sd
641           Seuls les mots cles simples MCSIMP font un traitement autre
642           que de transmettre aux fils
643       """
644       #print "delete_concept",self,sd
645       for etape in self.etapes :
646         etape.delete_concept(sd)
647
648    def replace_concept_after_etape(self,etape,old_sd,sd):
649       """
650           Met à jour les étapes du JDC qui sont après etape en fonction
651           du remplacement du concept sd
652       """
653       index = self.etapes.index(etape)+1
654       if index == len(self.etapes) :
655          return # etape est la dernière étape du jdc ...on ne fait rien !
656       for child in self.etapes[index:]:
657         child.replace_concept(old_sd,sd)
658
659    def update_concept_after_etape(self,etape,sd):
660       """
661           Met à jour les étapes du JDC qui sont après etape en fonction
662           de la modification (principalement nommage) du concept sd
663       """
664       if etape is None:
665          #On traite toutes les etapes
666          index=0
667       else:
668          index = self.etapes.index(etape)+1
669       if index == len(self.etapes) :
670          return # etape est la dernière étape du jdc ...on ne fait rien !
671       for child in self.etapes[index:]:
672         child.update_concept(sd)
673
674    def dump_state(self):
675       print "JDC.state: ",self.state
676       for etape in self.etapes :
677          print etape.nom+".state: ",etape.state
678       
679    def change_unit(self,unit,etape,old_unit):
680       #print "change_unit",unit,etape,old_unit
681       #print id(self.recorded_units),self.recorded_units
682       #if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
683       self.record_unit(unit,etape)
684
685    def record_unit(self,unit,etape):
686       """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
687       #print "record_unit",unit,etape
688       if unit is None:
689          # Cas de POURSUITE
690          self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
691       else:
692          self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
693       #print id(self.recorded_units),self.recorded_units
694       #print self.recorded_units.get(None,(None,"",{}))[2]
695       #print self.recorded_units.get(None,(None,"",{}))[2].get(None,(None,"",{}))
696
697    def changefichier(self,fichier):
698        self.fin_modif()
699
700    def eval_in_context(self,valeur,etape):
701       """ Tente d'evaluer valeur dans le contexte courant de etape
702           Retourne le parametre valeur inchange si l'evaluation est impossible
703       """
704       #contexte initial du jdc
705       context=self.condition_context.copy()
706       #contexte courant des concepts. Il contient les parametres
707       context.update(self.get_contexte_avant(etape))
708       try :
709          objet = eval(valeur,context)
710          return objet
711       except:
712          #traceback.print_exc()
713          pass
714       return valeur
715
716 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
717    def supprime(self):
718       #print "supprime",self
719       Noyau.N_JDC.JDC.supprime(self)
720    #   self.appli=None
721    #   self.g_context={}
722    #   self.const_context={}
723    #   self.sds=[]
724    #   self.sds_dict={}
725    #   self.mc_globaux={}
726    #   self.current_context={}
727    #   self.condition_context={}
728    #   self.etapes_niveaux=[]
729    #   self.niveau=None
730    #   self.params=[]
731    #   self.fonctions=[]
732    #   self._etape_context=None
733    #   self.etapes=[]
734        
735 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
736    def register(self,etape):
737       """
738            Cette méthode ajoute  etape dans la liste
739            des etapes self.etapes et retourne l identificateur d'étape
740            fourni par l appel a g_register
741
742            A quoi sert editmode ?
743               - Si editmode vaut 1, on est en mode edition de JDC. On cherche
744                 à enregistrer une étape que l'on a créée avec eficas (en passant
745                 par addentite) auquel cas on ne veut récupérer que son numéro
746                 d'enregistrement et c'est addentité qui l'enregistre dans
747                 self.etapes à la bonne place...
748               - Si editmode vaut 0, on est en mode relecture d'un fichier de
749                 commandes et on doit enregistrer l'étape à la fin de self.etapes
750                 (dans ce cas l'ordre des étapes est bien l'ordre chronologique
751                 de leur création   )
752       """
753       if not self.editmode:
754          self.etapes.append(etape)
755       else:
756          pass
757       return self.g_register(etape)
758
759 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
760    def NommerSdprod(self,sd,sdnom,restrict='non'):
761       """
762           Nomme la SD apres avoir verifie que le nommage est possible :
763           nom non utilise
764           Si le nom est deja utilise, leve une exception
765           Met le concept créé dans le concept global g_context
766       """
767       # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
768       # Le dictionnaire g_context ne représente pas le contexte
769       # effectif avant une étape.
770       # Il faut utiliser get_contexte_avant avec indication de l'étape
771       # traitée.
772       # Cette etape est indiquee par l'attribut _etape_context qui a ete
773       # positionné préalablement par un appel à set_etape_context
774
775       if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
776
777       if self._etape_context:
778          o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
779       else:
780          o=self.sds_dict.get(sdnom,None)
781
782       if isinstance(o,ASSD):
783          raise AsException("Nom de concept deja defini : %s" % sdnom)
784
785       # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
786       # Ajoute a la creation (appel de reg_sd).
787       self.sds_dict[sdnom]=sd
788       sd.nom=sdnom
789
790       # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
791       if restrict == 'non':
792          self.g_context[sdnom]=sd
793
794 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
795    def delete_concept_after_etape(self,etape,sd):
796       """
797           Met à jour les étapes du JDC qui sont après etape en fonction
798           de la disparition du concept sd
799       """
800       index = self.etapes.index(etape)+1
801       if index == len(self.etapes) :
802          return # etape est la dernière étape du jdc ...on ne fait rien !
803       for child in self.etapes[index:]:
804         child.delete_concept(sd)
805
806 #ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer
807
808    def get_file(self,unite=None,fic_origine=''):
809       """
810           Retourne le nom du fichier correspondant à un numero d'unité
811           logique (entier) ainsi que le source contenu dans le fichier
812       """
813       if self.appli :
814          # Si le JDC est relié à une application maitre, on délègue la recherche
815          file,text= self.appli.get_file(unite,fic_origine)
816       else:
817          file = None
818          if unite != None:
819             if os.path.exists("fort."+str(unite)):
820                file= "fort."+str(unite)
821          if file == None :
822             raise AsException("Impossible de trouver le fichier correspondant"
823                                " a l unite %s" % unite)
824          if not os.path.exists(file):
825             raise AsException("%s n'est pas un fichier existant" % unite)
826          fproc=open(file,'r')
827          text=fproc.read()
828          fproc.close()
829       #if file == None : return None,None
830       text=string.replace(text,'\r\n','\n')
831       if file:
832          linecache.cache[file]=0,0,string.split(text,'\n'),file
833       return file,text
834
835    def isvalid(self,cr='non'):
836      if hasattr(self,'valid'): old_valid=self.valid
837      else:old_valid=0
838      valid=Validation.V_JDC.JDC.isvalid(self,cr)
839      if valid != old_valid:
840        CONNECTOR.Emit(self,"valid")
841      return valid