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