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