Salome HOME
modif du 1010
[tools/eficas.git] / Ihm / I_JDC.py
1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2013   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 """
21 """
22 # Modules Python
23 import types,traceback,sys,os
24 import string,linecache
25 from Extensions.i18n import tr
26 from Extensions.eficas_exception import EficasException
27
28
29 # Modules Eficas
30 import I_OBJECT
31 import Noyau
32 from Noyau.N_ASSD import ASSD
33 #from Noyau.N_LASSD import LASSD
34 from Noyau.N_ETAPE import ETAPE
35 from Noyau.N_Exception import AsException
36 from Extensions import commentaire,parametre,parametre_eval
37 import CONNECTOR
38 import Validation
39
40 class LASSD:
41    pass
42
43 class JDC(I_OBJECT.OBJECT):
44    """
45    """
46    def __init__(self):
47       self.editmode=0
48       self.etapes_niveaux=[]
49       self.niveau=self
50       self.params=[]
51       self.fonctions=[]
52       self._etape_context=None
53       self.recorded_units={}
54       self.old_recorded_units={}
55  
56
57    def get_index(self,objet):
58       """
59         Retourne la position d'objet dans la liste self
60       """
61       return self.etapes.index(objet)
62
63    def get_sd_avant_du_bon_type(self,etape,types_permis):
64       """
65           Retourne la liste des concepts avant etape d'un type acceptable
66       """
67       d=self.get_contexte_avant(etape)
68       
69       
70       l=[]
71       for k,v in d.items():
72         if type(v) != types.InstanceType and not isinstance(v,object): continue
73         # On considere que seul assd indique un type quelconque pas CO
74         elif self.assd in types_permis :
75            if v.etape.sdnom != "sansnom" : l.append(k)
76         elif self.est_permis(v,types_permis):
77            if v.etape.sdnom != "sansnom" : l.append(k)
78       l.sort()
79       return l
80
81    def get_variables(self,etape):
82       etapeStop=etape
83       l=[]
84       for etapeTraitee in self.etapes :
85           if etapeTraitee==etapeStop:
86              break
87           if etapeTraitee.nom == 'VARIABLE' :
88              variable=etapeTraitee.get_mocle('ModelVariable')
89              if variable != None :
90                 l.append(variable.nom)
91       return l
92
93    def get_distributions(self,etape):
94       etapeStop=etape
95       l=[]
96       for etapeTraitee in self.etapes :
97           if etapeTraitee==etapeStop: break
98           if etapeTraitee.nom == 'DISTRIBUTION' and etapeTraitee.sd !=None : l.append(etapeTraitee.sd.nom)
99       return l
100
101
102    #def set_Copules_recalcule_etat(self):
103    #   for etapeTraitee in self.etapes :
104    #       if etapeTraitee.nom == 'CORRELATION' :
105              #Matrix=etapeTraitee.get_child('Matrix')
106              #if Matrix !=None :
107    #             Correlation=etapeTraitee.get_child('CorrelationMatrix')
108    #             if Correlation !=None : Correlation.state='arecalculer'
109              #   Matrix.state='arecalculer'
110      
111    #def recalcule_etat_correlation(self):
112    #   for etapeTraitee in self.etapes :
113    #       if etapeTraitee.nom == 'CORRELATION' :
114              #Matrix=etapeTraitee.get_child('Matrix')
115              #if Matrix !=None :
116    #             Matrix.state='arecalculer'
117    #             Correlation=Matrix.get_child('CorrelationMatrix')
118    #             if Correlation !=None : Correlation.state='arecalculer'
119    #                Correlation.isvalid()
120    #             Matrix.isvalid()
121    #             etapeTraitee.state='arecalculer'
122    #          if etapeTraitee.state=='arecalculer': etapeTraitee.isvalid()
123                 
124    def recalcule_etat_correlation(self):
125       for etapeTraitee in self.etapes :
126           if etapeTraitee.nom == 'CORRELATION' :
127              Correlation=etapeTraitee.get_child('CorrelationMatrix')
128              if Correlation !=None : 
129                   Correlation.state='arecalculer'
130                   Correlation.isvalid()
131              etapeTraitee.isvalid()
132
133    def recalcule_validite_apres_changement_global_jdc(self):
134         #print "je passe dans recalcule_validite_apres_changement_global_jdc"
135         try :
136           liste=self.get_jdc_root().cata[0].liste_condition
137         except :
138           liste=()
139         for etapeTraitee in self.etapes :
140            if etapeTraitee.nom not in liste: continue
141            self.forceRecalculBloc(etapeTraitee)
142            etapeTraitee.state='arecalculer'
143            etapeTraitee.isvalid()
144
145         
146    def forceRecalculBloc(self,objet):
147        # Attention : certains objets deviennent None quand on recalcule 
148        # les conditions d existence des blocs
149        if objet != None:  objet.state='arecalculer'
150        if hasattr(objet,'liste_mc_presents'):
151           for childNom in objet.liste_mc_presents():
152               child=objet.get_child(childNom)
153               if hasattr(objet,'_update_condition_bloc'):objet._update_condition_bloc()
154               self.forceRecalculBloc(child)
155        
156    
157    def get_sd_avant_du_bon_type_pour_type_de_base(self,etape,type):
158       """
159           Retourne la liste des concepts avant etape d'1 type de base acceptable
160           Attention different de la routine precedente : 1 seul type passe en parametre
161           Teste sur issubclass et par sur le type permis
162       """
163       d=self.get_contexte_avant(etape)
164       l=[]
165       try :
166          typeverif=self.cata[0].__dict__[type]
167       except :
168          return l
169       for k,v in d.items():
170         if issubclass(v.__class__,typeverif): 
171            l.append(k)
172       l.sort()
173       return l
174
175    def cherche_list_avant(self,etape,valeur):
176        d=self.get_contexte_avant(etape)
177        for k,v in d.items():
178           if issubclass(v.__class__,LASSD):
179              if k == valeur :
180                 return k
181         # Attention pour enlever les . a la fin des pretendus reels
182              if k == valeur[0:-1] :
183                 return v
184        return None
185
186    def est_permis(self,v,types_permis):
187       for type_ok in types_permis:
188           if type_ok in ('R','I','C','TXM') and v in self.params : 
189              return 1
190           elif type_ok == 'R' and v.__class__.__name__ == 'reel' : 
191              return 1
192           elif type_ok == 'I' and v.__class__.__name__ == 'entier' : 
193              return 1
194           elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : 
195              return 1
196           elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : 
197              return 1
198           elif type(type_ok) != types.ClassType and not isinstance(type_ok,type): 
199              continue
200           elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
201              return 1
202       return 0
203
204    def addentite(self,name,pos):
205       """
206           Ajoute une entite :
207           Si name est le nom d une commande ou un commentaire ajoute 
208           une etape au JDC
209           Sinon remonte une erreur
210       """
211       self.init_modif()
212       self.editmode=1
213       if name == "COMMENTAIRE" :
214         # ajout d'un commentaire
215         self.set_current_step()
216         ind = 1
217         for child in self.etapes :
218           from Extensions import commentaire
219           if isinstance(child,commentaire.COMMENTAIRE):
220             ind = ind+1
221         objet = commentaire.COMMENTAIRE('',parent=self)
222         objet.nom = "_comm_"+`ind`
223         if pos == None : pos = 0
224         self.etapes.insert(pos,objet)
225         self.reset_context()
226         self.editmode=0
227         self.active_etapes()
228         CONNECTOR.Emit(self,"add",objet)
229         self.fin_modif()
230         return objet
231       elif name == "PARAMETRE":
232         # ajout d'un parametre
233         self.set_current_step()
234         nom_param = '_param_'+str(len(self.params)+1)
235         objet = parametre.PARAMETRE(nom=nom_param)
236         if pos == None : pos = 0
237         self.etapes.insert(pos,objet)
238         self.reset_context()
239         self.editmode=0
240         self.active_etapes()
241         CONNECTOR.Emit(self,"add",objet)
242         self.fin_modif()
243         return objet
244       elif name == "PARAMETRE_EVAL":
245         # ajout d'un parametre EVAL
246         self.set_current_step()
247         nom_param = '_param_'+str(len(self.params)+1)
248         objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
249         if pos == None : pos = 0
250         self.etapes.insert(pos,objet)
251         self.reset_context()
252         self.editmode=0
253         self.active_etapes()
254         CONNECTOR.Emit(self,"add",objet)
255         self.fin_modif()
256         return objet
257       elif type(name)==types.InstanceType:
258         # on est dans le cas ou on veut ajouter une commande deja 
259         # existante (par copie donc)
260         # on est donc necessairement en mode editeur ...
261         objet = name
262         # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
263         from Extensions import commentaire
264         if not( isinstance (objet,commentaire.COMMENTAIRE)):
265            objet.reparent(self)
266         self.set_current_step()
267         if isinstance(objet,ETAPE):
268           if objet.nom_niveau_definition == 'JDC':
269             # l'objet depend directement du JDC
270             objet.niveau = self
271           else:
272             # l'etape depend d'un niveau et non directement du JDC :
273             # il faut l'enregistrer dans le niveau de parent
274             objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
275             objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
276         self.etapes.insert(pos,objet)
277         self.reset_context()
278         # il faut verifier que les concepts utilises par objet existent bien
279         # a ce niveau d'arborescence
280         objet.verif_existence_sd()
281         objet.update_mc_global()
282         self.editmode=0
283         self.active_etapes()
284         CONNECTOR.Emit(self,"add",objet)
285         self.fin_modif()
286         return objet
287       else :
288         # On veut ajouter une nouvelle commande
289         try:
290           self.set_current_step()
291           cmd=self.get_cmd(name)
292           # L'appel a make_objet n'a pas pour effet d'enregistrer l'etape
293           # aupres du step courant car editmode vaut 1
294           # Par contre elle a le bon parent grace a set_current_step
295           e=cmd.make_objet()
296           if pos == None : pos = 0
297           self.etapes.insert(pos,e)
298           self.reset_current_step()
299           self.reset_context()
300           self.editmode=0
301           self.active_etapes()
302           CONNECTOR.Emit(self,"add",e)
303           self.fin_modif()
304           return e
305         except AsException,e:
306           traceback.print_exc()
307           self.reset_current_step()
308           self.editmode=0
309           raise AsException(tr("Impossible d'ajouter la commande")+name + '\n')
310         except:
311         #else :
312           traceback.print_exc()
313           self.reset_current_step()
314           self.editmode=0
315           raise AsException(tr("Impossible d ajouter la commande")+name)
316
317    def close(self):
318       #print "JDC.close",self
319       for etape in self.etapes:
320           if hasattr(etape,"close"):etape.close()
321       CONNECTOR.Emit(self,"close")
322
323    def set_current_step(self):
324       CONTEXT.unset_current_step()
325       CONTEXT.set_current_step(self)
326
327    def reset_current_step(self):
328       CONTEXT.unset_current_step()
329
330    def liste_mc_presents(self):
331       return []
332
333    def get_sd_avant_etape(self,nom_sd,etape):
334       return self.get_contexte_avant(etape).get(nom_sd,None)
335
336    def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
337       """ 
338            Cette methode retourne la SD sd de nom nom_sd qui est eventuellement
339            definie apres etape en tenant compte des concepts detruits
340            Si avec vaut 'non' exclut etape de la recherche
341       """
342       #print "JDC.get_sd_apres_etape_avec_detruire",nom_sd,sd
343       ietap=self.etapes.index(etape)
344       if avec == 'non':ietap=ietap+1
345       d={nom_sd:sd}
346       for e in self.etapes[ietap:]:
347          if e.isactif():
348             e.update_context(d)
349             autre_sd=d.get(nom_sd,None)
350             if autre_sd is None:
351               # Le concept a ete detruit. On interrompt la recherche car il n'y a
352               # pas eu de redefinition du concept (il n'y a pas de conflit potentiel).
353               return None
354             if autre_sd is not sd :
355               # L'etape produit un concept different de meme nom. La situation n'est
356               # pas saine (sauf peut etre si reuse ???)
357               if hasattr(e,'reuse') and e.reuse == autre_sd:
358                  # Le concept etant reutilise, on interrompt la recherche. 
359                  # On considere qu'il n'y a pas de nouveau concept defini
360                  # meme si dans les etapes suivantes le concept est detruit
361                  # et un concept de meme nom cree.
362                  # AVERIFIER : avec reuse le concept devrait etre le meme
363                  # le passage par ici est tres improbable
364                  return None
365               else:
366                  # Le concept est produit par l'etape (Il y a conflit potentiel).
367                  # Le concept est redefini par une etape posterieure.
368                  return autre_sd
369       # Pas de destruction du concept ni de redefinition. On retourne le
370       # concept initial
371       return sd
372
373    def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
374       """ 
375            Cette methode retourne la SD de nom nom_sd qui est eventuellement
376            definie apres etape 
377            Si avec vaut 'non' exclut etape de la recherche
378       """
379       ietap=self.etapes.index(etape)
380       if avec == 'non':ietap=ietap+1
381       for e in self.etapes[ietap:]:
382         sd=e.get_sdprods(nom_sd)
383         if sd:
384           if hasattr(e,'reuse'):
385             if e.reuse != sd:
386               return sd
387       return None
388
389    def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
390       """
391            Fonction: retourne la SD de nom nom_sd qui est eventuellement
392            definie avant ou apres etape
393            Permet de verifier si un concept de meme nom existe dans le perimetre 
394            d'une etape
395            Si avec vaut 'non' exclut etape de la recherche
396       """
397       sd=self.get_sd_avant_etape(nom_sd,etape)
398       if sd:return sd
399       return self.get_sd_apres_etape(nom_sd,etape,avec)
400
401    def get_contexte_apres(self,etape):
402       """
403          Retourne le dictionnaire des concepts connus apres etape
404          On tient compte des commandes qui modifient le contexte
405          comme DETRUIRE ou les macros
406          Si etape == None, on retourne le contexte en fin de JDC
407       """
408       if not etape: return self.get_contexte_avant(etape)
409
410       d=self.get_contexte_avant(etape)
411       if etape.isactif():etape.update_context(d)
412       self.index_etape_courante=self.index_etape_courante+1
413       return d
414
415    def active_etapes(self):
416       """
417           Cette methode a pour fonction de desactiver les etapes qui doivent
418           l'etre cad, dans le cas d'ASTER, les etapes qui ne sont pas 
419           comprises entre le premier DEBUT/POURSUITE et le premier FIN 
420           et rendre actives les autres
421       """
422       if self.definition.code == 'ASTER' :
423          # Seulement pour ASTER :
424          # Avant DEBUT actif vaut 0
425          # Apres DEBUT et avant le 1er FIN actif vaut 1
426          # Apres le 1er FIN actif vaut -1
427          actif=0
428       else:
429          actif=1
430       for etape in self.etapes:
431         if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
432         if actif == 1:
433            etape.active()
434         else:
435            etape.inactive()
436         if etape.nom == 'FIN':actif=-1
437
438    def deplaceEntite(self,indexNoeudACopier,indexNoeudOuColler,pos):
439       """
440           Pour le cut
441       """
442       if indexNoeudACopier==indexNoeudOuColler:return
443       etapeACopier=self.etapes[indexNoeudACopier]
444       try :
445         sd=self.etapes[indexNoeudACopier].sd
446       except :
447         sd=None
448       if pos=='before' and indexNoeudOuColler==0 : 
449          self.etapes2=[etapeACopier,]+self.etapes[0:indexNoeudACopier]+self.etapes[indexNoeudACopier+1:]
450       elif indexNoeudACopier < indexNoeudOuColler :
451          self.etapes2=self.etapes[0:indexNoeudACopier]+self.etapes[indexNoeudACopier+1:indexNoeudOuColler+1]+[etapeACopier,]+self.etapes[indexNoeudOuColler+1:]
452       else:
453          self.etapes2=self.etapes[0:indexNoeudOuColler+1]+[etapeACopier,]+self.etapes[indexNoeudOuColler+1:indexNoeudACopier]+self.etapes[indexNoeudACopier+1:]
454       self.etapes=self.etapes2
455       if indexNoeudACopier < indexNoeudOuColler :
456         self.delete_concept_entre_etapes(indexNoeudACopier,indexNoeudOuColler,sd)
457       self.reset_context()
458       for e in self.etapes :
459          e.state = 'modified'
460       self.control_context_apres(None)
461       return 1
462
463
464    def suppentite(self,etape) :
465       """  
466           Cette methode a pour fonction de supprimer une etape dans 
467           un jeu de commandes
468           Retourne 1 si la suppression a pu etre effectuee,
469           Retourne 0 dans le cas contraire
470       """
471       #PN correction de bugs 
472       if etape not in self.etapes: return 0
473
474       self.init_modif()
475       index_etape=self.etapes.index(etape)
476
477       self.etapes.remove(etape)
478
479       if etape.niveau is not self:
480         # Dans ce cas l'etape est enregistree dans un niveau
481         # Il faut la desenregistrer
482         etape.niveau.unregister(etape)
483
484       etape.supprime_sdprods()
485       etape.close()
486       etape.supprime()
487       self.active_etapes()
488
489       # Apres suppression de l'etape il faut controler que les etapes
490       # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
491       if index_etape > 0: 
492          index_etape=index_etape-1
493          etape=self.etapes[index_etape]
494       else:
495          etape=None
496       self.control_context_apres(etape)
497      
498       self.reset_context()
499       CONNECTOR.Emit(self,"supp",etape)
500       self.fin_modif()
501       return 1
502
503    def control_context_apres(self,etape):
504       """
505          Cette methode verifie que les etapes apres l'etape etape
506          ont bien des concepts produits acceptables (pas de conflit de 
507          nom principalement)
508          Si des concepts produits ne sont pas acceptables ils sont supprimes.
509          Effectue les verifications sur les etapes du jdc mais aussi sur les
510          jdc parents s'ils existent.
511       """
512       #print "control_context_apres",self,etape
513       #Regularise les etapes du jdc apres l'etape etape
514       self.control_jdc_context_apres(etape)
515
516    def control_jdc_context_apres(self,etape):
517       """
518           Methode semblable a control_context_apres mais ne travaille
519           que sur les etapes et sous etapes du jdc
520       """
521       #print "control_jdc_context_apres",self,etape
522       if etape is None:
523          # on demarre de la premiere etape
524          index_etape=0
525       else:
526          index_etape=self.etapes.index(etape)+1
527
528       try:
529          etape=self.etapes[index_etape]
530       except:
531          #derniere etape du jdc : rien a faire
532          return
533
534       context=self.get_contexte_avant(etape)
535
536       for e in self.etapes[index_etape:]:
537           e.control_sdprods(context)
538           e.update_context(context)
539
540    def analyse(self):
541       self.compile()
542       if not self.cr.estvide():return
543       self.exec_compile()
544       self.active_etapes()
545
546    def register_parametre(self,param):
547       """
548           Cette methode sert a ajouter un parametre dans la liste des parametres
549       """
550       self.params.append(param)
551
552    def register_fonction(self,fonction):
553       """
554           Cette methode sert a ajouter une fonction dans la liste des fonctions
555       """
556       self.fonctions.append(fonction)
557
558    def delete_param(self,param):
559       """
560           Supprime le parametre param de la liste des parametres
561           et du contexte gobal
562       """
563       if param in self.params : self.params.remove(param)
564       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
565
566    def get_parametres_fonctions_avant_etape(self,etape):
567       """
568           Retourne deux elements :
569           - une liste contenant les noms des parametres (constantes ou EVAL) 
570             definis avant etape
571           - une liste contenant les formules definies avant etape
572       """
573       l_constantes = []
574       l_fonctions = []
575       # on recupere le contexte avant etape
576       # on ne peut mettre dans les deux listes que des elements de ce contexte
577       d=self.get_contexte_avant(etape)
578       # construction de l_constantes
579       for param in self.params:
580         nom = param.nom
581         if not nom : continue
582         if d.has_key(nom): l_constantes.append(nom)
583       # construction de l_fonctions
584       for form in self.fonctions:
585         nom = form.nom
586         if not nom : continue
587         if d.has_key(nom): l_fonctions.append(form.get_formule())
588
589       # on ajoute les concepts produits par DEFI_VALEUR
590       # XXX On pourrait peut etre faire plutot le test sur le type
591       # de concept : entier, reel, complexe, etc.
592       for k,v in d.items():
593          if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
594             l_constantes.append(k)
595
596       # on retourne les deux listes
597       return l_constantes,l_fonctions
598
599    def get_nb_etapes_avant(self,niveau):
600       """ 
601           Retourne le nombre d etapes avant le debut de niveau
602       """
603       nb=0
604       for niv in self.etapes_niveaux:
605         if niv == niveau:break
606         nb=nb+len(niv.etapes)
607       return nb
608
609    def init_modif(self):
610       """
611       Methode appelee au moment ou une modification va etre faite afin de 
612       declencher d'eventuels traitements pre-modification
613       """
614       #print "init_modif",self
615       self.state = 'modified'
616
617    def fin_modif(self):
618       #print "fin_modif",self
619       CONNECTOR.Emit(self,"valid")
620       self.isvalid()
621       pass
622
623    def deep_update_condition_bloc(self):
624       # pour le moment, on ne fait rien
625       self.get_jdc_root().recalcule_validite_apres_changement_global_jdc()
626       #raise EficasException(tr("Pas implemente"))
627
628    def update_condition_bloc(self):
629       # pour le moment, on ne fait rien
630       raise EficasException(tr("Pas implemente"))
631
632    def get_liste_mc_inconnus(self):
633      """
634      Retourne une liste contenant les mots-cles inconnus a la relecture du JDC
635      """
636      # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
637      l_mc = []
638      for etape in self.etapes :
639          if etape.isactif() :
640             if not etape.isvalid() :
641                l = etape.get_liste_mc_inconnus()
642                if l : l_mc.extend(l)
643      return l_mc    
644
645    def get_genealogie_precise(self):
646       return []
647
648    def get_genealogie(self):
649       """
650           Retourne la liste des noms des ascendants de l'objet self
651           jusqu'a la premiere ETAPE parent.
652       """
653       return []
654
655    def get_liste_cmd(self):
656       """
657           Retourne la liste des commandes du catalogue
658       """
659       return self.niveau.definition.get_liste_cmd()
660
661    def get_groups(self):
662       """
663           Retourne la liste des groupes
664       """
665       return self.niveau.definition.liste_groupes,self.niveau.definition.dict_groupes
666
667    def set_etape_context(self,etape):
668       """
669           Positionne l'etape qui sera utilisee dans NommerSdProd pour
670           decider si le concept passe pourra etre  nomme
671       """
672       self._etape_context=etape
673
674    def reset_context(self):
675       """ 
676           Cette methode reinitialise le contexte glissant pour pouvoir
677           tenir compte des modifications de l'utilisateur : craation
678           de commandes, nommage de concepts, etc.
679       """
680       #print "reset_context",self,self.nom
681       self.current_context={}
682       self.index_etape_courante=0
683       ind={}
684       for i,etape in enumerate(self.etapes):
685         ind[etape]=i
686       self.index_etapes=ind
687
688    #   for etape in self.etapes:
689    #       etape.reset_context()
690
691    def del_sdprod(self,sd):
692       """
693           Supprime la SD sd de la liste des sd et des dictionnaires de contexte
694       """
695       #print "del_sdprod",self,sd
696       #print "del_sdprod",self.sds
697       #print "del_sdprod",self.g_context
698       #print "del_sdprod",self.sds_dict
699       #if sd in self.sds : self.sds.remove(sd)
700       if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
701       if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
702
703    def del_param(self,param):
704       """
705           Supprime le parametre param de la liste des paramatres
706           et du contexte gobal
707       """
708       if param in self.params : self.params.remove(param)
709       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
710
711    def del_fonction(self,fonction):
712       """
713           Supprime la fonction fonction de la liste des fonctions
714           et du contexte gobal
715       """
716       if fonction in self.fonctions : self.fonctions.remove(fonction)
717       if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
718
719    def append_sdprod(self,sd):
720       """
721           Ajoute la SD sd a la liste des sd en verifiant au prealable qu'une SD de
722           meme nom n'existe pas deja
723       """
724       if sd == None or sd.nom == None:return
725
726       o=self.sds_dict.get(sd.nom,None)
727       if isinstance(o,ASSD):
728          raise AsException(tr("Nom de concept deja defini "+ sd.nom))
729       self.sds_dict[sd.nom]=sd
730       self.g_context[sd.nom] = sd
731       #if sd not in self.sds : self.sds.append(sd)
732
733    def append_param(self,param):
734       """
735           Ajoute le parametre param a la liste des params
736           et au contexte global
737       """
738       # il faudrait verifier qu'un parametre de meme nom n'existe pas deja !!!
739       if param not in self.params : self.params.append(param)
740       self.g_context[param.nom]=param
741
742    def append_fonction(self,fonction):
743       """
744           Ajoute la fonction fonction a la liste des fonctions
745           et au contexte global
746       """
747       # il faudrait verifier qu'une fonction de meme nom n'existe pas deja !!!
748       if fonction not in self.fonctions : self.fonctions.append(fonction)
749       self.g_context[fonction.nom]=fonction
750
751    def delete_concept(self,sd):
752       """
753           Inputs :
754              - sd=concept detruit
755           Fonction :
756           Mettre a jour les etapes du JDC suite a la disparition du
757           concept sd
758           Seuls les mots cles simples MCSIMP font un traitement autre
759           que de transmettre aux fils
760       """
761       for etape in self.etapes :
762         etape.delete_concept(sd)
763         #PN PN PN pour les matrices ????
764         #self.get_variables_avant(etape)
765
766    def replace_concept_after_etape(self,etape,old_sd,sd):
767       """
768           Met a jour les etapes du JDC qui sont apres etape en fonction
769           du remplacement du concept sd
770       """
771       index = self.etapes.index(etape)+1
772       if index == len(self.etapes) :
773          return # etape est la derniere etape du jdc ...on ne fait rien !
774       for child in self.etapes[index:]:
775         child.replace_concept(old_sd,sd)
776
777    def update_concept_after_etape(self,etape,sd):
778       """
779           Met a jour les etapes du JDC qui sont apres etape en fonction
780           de la modification (principalement nommage) du concept sd
781       """
782       if etape is None:
783          #On traite toutes les etapes
784          index=0
785       else:
786          index = self.etapes.index(etape)+1
787       if index == len(self.etapes) :
788          return # etape est la derniere etape du jdc ...on ne fait rien !
789       for child in self.etapes[index:]:
790         child.update_concept(sd)
791
792    def dump_state(self):
793       print "JDC.state: ",self.state
794       for etape in self.etapes :
795          print etape.nom+".state: ",etape.state
796       
797    def change_unit(self,unit,etape,old_unit):
798       #print "change_unit",unit,etape,old_unit
799       #print id(self.recorded_units),self.recorded_units
800       #if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
801       self.record_unit(unit,etape)
802
803    def record_unit(self,unit,etape):
804       """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
805       #print "record_unit",unit,etape
806       if unit is None:
807          # Cas de POURSUITE
808          self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
809       else:
810          self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
811       #print id(self.recorded_units),self.recorded_units
812       #print self.recorded_units.get(None,(None,"",{}))[2]
813       #print self.recorded_units.get(None,(None,"",{}))[2].get(None,(None,"",{}))
814
815    def changefichier(self,fichier):
816        self.fin_modif()
817
818    def eval_in_context(self,valeur,etape):
819       """ Tente d'evaluer valeur dans le contexte courant de etape
820           Retourne le parametre valeur inchange si l'evaluation est impossible
821       """
822       #contexte initial du jdc
823       context=self.condition_context.copy()
824       #contexte courant des concepts. Il contient les parametres
825       context.update(self.get_contexte_avant(etape))
826       try :
827          objet = eval(valeur,context)
828          return objet
829       except:
830          #traceback.print_exc()
831          pass
832       return valeur
833
834 #ATTENTION SURCHARGE : cette methode doit etre gardee en synchronisation avec celle de Noyau
835    def supprime(self):
836       Noyau.N_JDC.JDC.supprime(self)
837       for etape in self.etapes:
838          etape.supprime()
839       self.appli=None
840       self.g_context={}
841       self.const_context={}
842       self.sds_dict={}
843       self.mc_globaux={}
844       self.current_context={}
845       self.condition_context={}
846       self.etapes_niveaux=[]
847       self.niveau=None
848       self.params=[]
849       self.fonctions=[]
850       self._etape_context=None
851       self.etapes=[]
852        
853 #ATTENTION SURCHARGE : cette methode doit etre gardee en synchronisation avec celle de Noyau
854    def register(self,etape):
855       """
856            Cette methode ajoute  etape dans la liste
857            des etapes self.etapes et retourne l identificateur d'etape
858            fourni par l appel a g_register
859
860            A quoi sert editmode ?
861               - Si editmode vaut 1, on est en mode edition de JDC. On cherche
862                 a enregistrer une etape que l'on a creee avec eficas (en passant
863                 par addentite) auquel cas on ne veut recuperer que son numero
864                 d'enregistrement et c'est addentite qui l'enregistre dans
865                 self.etapes a la bonne place...
866               - Si editmode vaut 0, on est en mode relecture d'un fichier de
867                 commandes et on doit enregistrer l'etape a la fin de self.etapes
868                 (dans ce cas l'ordre des etapes est bien l'ordre chronologique
869                 de leur creation   )
870       """
871       if not self.editmode:
872          self.etapes.append(etape)
873          self.index_etapes[etape] = len(self.etapes) - 1
874       else:
875          pass
876       return self.g_register(etape)
877
878 #ATTENTION SURCHARGE : cette methode doit etre gardee en synchronisation avec celle de Noyau
879    def NommerSdprod(self,sd,sdnom,restrict='non'):
880       """
881           Nomme la SD apres avoir verifie que le nommage est possible :
882           nom non utilise
883           Si le nom est deja utilise, leve une exception
884           Met le concept cree dans le concept global g_context
885       """
886       # XXX En mode editeur dans EFICAS, le nommage doit etre gere differemment
887       # Le dictionnaire g_context ne represente pas le contexte
888       # effectif avant une etape.
889       # Il faut utiliser get_contexte_avant avec indication de l'etape
890       # traitee.
891       # Cette etape est indiquee par l'attribut _etape_context qui a ete
892       # positionne prealablement par un appel a set_etape_context
893
894       if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
895
896       if self._etape_context:
897          o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
898       else:
899          o=self.sds_dict.get(sdnom,None)
900
901       if isinstance(o,ASSD):
902          raise AsException(tr(" Nom de concept deja  defini : "+ sdnom))
903
904       # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
905       # Ajoute a la creation (appel de reg_sd).
906       self.sds_dict[sdnom]=sd
907       sd.nom=sdnom
908
909       # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
910       if restrict == 'non':
911          self.g_context[sdnom]=sd
912
913    def delete_concept_entre_etapes(self,index1,index2,sd):
914       if index2 <= index1 :return
915       for child in self.etapes[index1:index2]:
916         child.delete_concept(sd)
917
918    def delete_concept_after_etape(self,etape,sd):
919       """
920           Met a jour les etapes du JDC qui sont apres etape en fonction
921           de la disparition du concept sd
922       """
923       index = self.etapes.index(etape)+1
924       if index == len(self.etapes) :
925          return # etape est la derniere etape du jdc ...on ne fait rien !
926       for child in self.etapes[index:]:
927         child.delete_concept(sd)
928
929 #ATTENTION SURCHARGE : les methodes ci-dessus surchargent des methodes de Noyau et Validation : a reintegrer
930
931    def get_file(self,unite=None,fic_origine=''):
932       """
933           Retourne le nom du fichier correspondant a un numero d'unite
934           logique (entier) ainsi que le source contenu dans le fichier
935       """
936       if self.appli is not None:
937          # Si le JDC est relie a une application maitre, on delegue la recherche
938          file,text= self.appli.get_file(unite,fic_origine)
939       else:
940          file = None
941          if unite != None:
942             if os.path.exists(u"fort."+str(unite)):
943                file= "fort."+str(unite)
944          if file == None :
945             raise AsException(tr("Impossible de trouver le fichier correspondant a l'unite "+str( unite)))
946          if not os.path.exists(file):
947             raise AsException(str(unite)+ tr(" n'est pas un fichier existant"))
948          fproc=open(file,'r')
949          text=fproc.read()
950          fproc.close()
951       #if file == None : return None,None
952       text=string.replace(text,'\r\n','\n')
953       if file:
954          linecache.cache[file]=0,0,string.split(text,'\n'),file
955       return file,text
956
957    def isvalid(self,cr='non'):
958      if hasattr(self,'valid'): old_valid=self.valid
959      else:old_valid=0
960      valid=Validation.V_JDC.JDC.isvalid(self,cr)
961      if valid != old_valid:
962        CONNECTOR.Emit(self,"valid")
963      return valid
964
965    def get_l_noms_etapes(self):
966       """ 
967           Retourne la liste des noms des étapes de self 
968       """
969       l=[]
970       for etape in self.etapes:
971         l.append(etape.nom)
972       return l