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