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