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