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