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