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