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