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