Salome HOME
CCAR: correction probleme de destruction de commande avec concept reuse
[tools/eficas.git] / Ihm / I_MACRO_ETAPE.py
1 # -*- coding: utf-8 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21 """
22 """
23 # Modules Python
24 import sys
25 import traceback,types,string
26
27 # Modules Eficas
28 import I_ETAPE
29 from Noyau.N_ASSD import ASSD
30
31 # import rajoutés suite à l'ajout de Build_sd --> à résorber
32 import Noyau, Validation.V_MACRO_ETAPE
33 from Noyau import N_Exception
34 from Noyau.N_Exception import AsException
35 import Accas # attention aux imports circulaires
36 # fin import à résorber
37
38 class MACRO_ETAPE(I_ETAPE.ETAPE):
39
40   def __init__(self):
41       self.typret=None
42       self.recorded_units={}
43
44   def get_sdprods(self,nom_sd):
45     """ 
46          Fonction : retourne le concept produit par l etape de nom nom_sd
47          s il existe sinon None
48     """
49     if self.sd and self.sd.nom == nom_sd :return self.sd
50     for co in self.sdprods:
51       if co.nom == nom_sd:return co
52     if type(self.definition.op_init) == types.FunctionType:
53       d={}
54       apply(self.definition.op_init,(self,d))
55       return d.get(nom_sd,None)
56     return None
57
58   def get_contexte_jdc(self,fichier,text):
59     """ 
60          Interprète text comme un texte de jdc et retourne le 
61          contexte final
62          cad le dictionnaire des sd disponibles à la dernière étape
63          Si text n'est pas un texte de jdc valide, retourne None
64          ou leve une exception
65          --> utilisée par ops.POURSUITE et INCLUDE
66     """
67     #print "get_contexte_jdc"
68     try:
69        # on essaie de créer un objet JDC auxiliaire avec un contexte initial
70        # Attention get_contexte_avant retourne un dictionnaire qui contient
71        # le contexte courant. Ce dictionnaire est reactualise regulierement.
72        # Si on veut garder l'etat du contexte fige, il faut en faire une copie.
73        context_ini = self.parent.get_contexte_avant(self).copy()
74
75        # Indispensable avant de creer un nouveau JDC
76        CONTEXT.unset_current_step()
77        args=self.jdc.args
78        prefix_include=None
79        if hasattr(self,'prefix'):
80           prefix_include=self.prefix
81        # ATTENTION : le dictionnaire recorded_units sert à memoriser les unites des 
82        # fichiers inclus. Il est preferable de garder le meme dictionnaire pendant
83        # tout le traitement et de ne pas le reinitialiser brutalement (utiliser 
84        # clear plutot) si on ne veut pas perdre la memoire des unites.
85        # En principe si la memorisation est faite au bon moment il n'est pas necessaire
86        # de prendre cette precaution mais ce n'est pas vrai partout.
87        old_recorded_units=self.recorded_units.copy()
88        #print "get_contexte_jdc",id(self.recorded_units)
89        #self.recorded_units.clear()
90
91        j=self.JdC_aux( procedure=text, nom=fichier,
92                                 appli=self.jdc.appli,
93                                 cata=self.jdc.cata,
94                                 cata_ord_dico=self.jdc.cata_ordonne_dico,
95                                 context_ini = context_ini,
96                                 jdc_pere=self.jdc,etape_include=self,
97                                 prefix_include=prefix_include,
98                                 recorded_units=self.recorded_units,
99                                 old_recorded_units=old_recorded_units,**args)
100
101        j.analyse()
102        # On récupère les étapes internes (pour validation)
103        self.etapes=j.etapes
104        self.jdc_aux=j
105        #print "get_contexte_jdc",id(self.etapes)
106     except:
107        traceback.print_exc()
108        # On force le contexte (etape courante) à self
109        CONTEXT.unset_current_step()
110        CONTEXT.set_current_step(self)
111        return None
112
113     if not j.cr.estvide():
114        # Erreurs dans l'INCLUDE. On garde la memoire du fichier 
115        # mais on n'insere pas les concepts
116        # On force le contexte (etape courante) à self
117        CONTEXT.unset_current_step()
118        CONTEXT.set_current_step(self)
119        raise Exception("Impossible de relire le fichier\n"+str(j.cr))
120
121     if not j.isvalid():
122        # L'INCLUDE n'est pas valide.
123        # on produit un rapport d'erreurs
124        # On force le contexte (etape courante) à self
125        cr=j.report()
126        CONTEXT.unset_current_step()
127        CONTEXT.set_current_step(self)
128        raise Exception("Le fichier include contient des erreurs\n"+str(cr))
129
130     # Si aucune erreur rencontrée
131     # On recupere le contexte de l'include verifie
132     #print "context_ini",j.context_ini
133     #print "g_context",j.g_context
134     try:
135        j_context=j.get_verif_contexte()
136     except:
137        CONTEXT.unset_current_step()
138        CONTEXT.set_current_step(self)
139        raise
140
141     #print "context_ini",j.context_ini
142
143     # On remplit le dictionnaire des concepts produits inclus
144     # en retirant les concepts présents dans le  contexte initial
145     # On ajoute egalement le concept produit dans le sds_dict du parent
146     # sans verification car on est sur (verification integrée) que 
147     # le nommage est possible
148     self.g_context.clear()
149     for k,v in j_context.items():
150        if not context_ini.has_key(k) or context_ini[k] != v:
151            self.g_context[k]=v
152            self.parent.sds_dict[k]=v
153
154
155     # On recupere le contexte courant
156     self.current_context=j.current_context
157     self.index_etape_courante=j.index_etape_courante
158     self.jdc_aux=j
159
160     # XXX j.supprime() ???
161     # On rétablit le contexte (etape courante) à self
162     CONTEXT.unset_current_step()
163     CONTEXT.set_current_step(self)
164     #print "context_ini",self.jdc_aux.context_ini
165
166     return j_context
167
168   def reevalue_sd_jdc(self):
169      """
170          Avec la liste des SD qui ont été supprimées, propage la 
171          disparition de ces SD dans toutes les étapes et descendants
172      """
173      #print "reevalue_sd_jdc"
174      l_sd_supp,l_sd_repl = self.diff_contextes()
175      for sd in l_sd_supp:
176         self.parent.delete_concept_after_etape(self,sd)
177      for old_sd,sd in l_sd_repl:
178         self.parent.replace_concept_after_etape(self,old_sd,sd)
179
180   def diff_contextes(self):
181      """ 
182          Réalise la différence entre les 2 contextes 
183          old_contexte_fichier_init et contexte_fichier_init
184          cad retourne la liste des sd qui ont disparu ou ne derivent pas 
185          de la meme classe et des sd qui ont ete remplacees
186      """
187      if not hasattr(self,'old_contexte_fichier_init'):return [],[]
188      l_sd_suppressed = []
189      l_sd_replaced = []
190      for old_key in self.old_contexte_fichier_init.keys():
191        if not self.contexte_fichier_init.has_key(old_key):
192          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
193            l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
194        else:
195          if isinstance(self.old_contexte_fichier_init[old_key],ASSD):
196             # Un concept de meme nom existe
197             old_class=self.old_contexte_fichier_init[old_key].__class__
198             if not isinstance(self.contexte_fichier_init[old_key],old_class):
199                # S'il n'est pas d'une classe derivee, on le supprime
200                l_sd_suppressed.append(self.old_contexte_fichier_init[old_key])
201             else:
202                l_sd_replaced.append((self.old_contexte_fichier_init[old_key],self.contexte_fichier_init[old_key]))
203      return l_sd_suppressed,l_sd_replaced
204       
205   def control_sdprods(self,d):
206       """
207           Cette methode doit updater le contexte fournit par
208           l'appelant en argument (d) en fonction de sa definition
209           tout en verifiant que ses concepts produits ne sont pas
210           deja definis dans le contexte
211       """
212       if hasattr(self,"fichier_unite"):
213          self.update_fichier_init(self.fichier_unite)
214          self.init_modif()
215
216       if type(self.definition.op_init) == types.FunctionType:
217         apply(self.definition.op_init,(self,d))
218       if self.sd:
219         if d.has_key(self.sd.nom):
220            # Le concept est deja defini
221            if self.reuse and self.reuse is d[self.sd.nom]:
222               # Le concept est reutilise : situation normale
223               pass
224            else:
225               # Redefinition du concept, on l'annule
226               #XXX on pourrait simplement annuler son nom pour conserver les objets
227               # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
228               self.sd=self.reuse=self.sdnom=None
229               self.init_modif()
230         else:
231            # Le concept n'est pas defini, on peut updater d
232            d[self.sd.nom]=self.sd
233       # On verifie les concepts a droite du signe =
234       for co in self.sdprods:
235         if d.has_key(co.nom) and co is not d[co.nom] :
236            self.delete_concept(co)
237         else:
238            d[co.nom]=co
239        
240   def supprime_sdprod(self,sd):
241       """
242          Supprime le concept produit sd s'il est produit par l'etape
243       """
244       if sd in self.sdprods:
245          self.init_modif()
246          self.parent.del_sdprod(sd)
247          self.sdprods.remove(sd)
248          self.fin_modif()
249          self.parent.delete_concept(sd)
250          return
251
252       if sd is not self.sd :return
253       if self.sd is not None :
254          self.init_modif()
255          self.parent.del_sdprod(sd)
256          self.sd=None
257          self.fin_modif()
258          self.parent.delete_concept(sd)
259
260   def supprime_sdprods(self):
261       """
262           Fonction: Lors de la destruction de la macro-etape, detruit tous les concepts produits
263           Un opérateur n a qu un concept produit
264           Une procedure n'en a aucun
265           Une macro en a en général plus d'un
266       """
267       #print "supprime_sdprods"
268       if self.reuse is not self.sd :
269          # l'étape n'est pas réentrante
270          # le concept retourné par l'étape est à supprimer car il était
271          # créé par l'étape
272          if self.sd != None :
273             self.parent.del_sdprod(self.sd)
274             self.parent.delete_concept(self.sd)
275       # On détruit les concepts à droite du signe =
276       for co in self.sdprods:
277          self.parent.del_sdprod(co)
278          self.parent.delete_concept(co)
279       # Si la macro a des etapes et des concepts inclus, on les detruit
280       for nom_sd,co in self.g_context.items():
281          if not isinstance(co,ASSD):continue
282          self.parent.del_sdprod(co)
283          self.parent.delete_concept(co)
284       # On met g_context à blanc
285       self.g_context={}
286
287   def delete_concept(self,sd):
288       """
289           Fonction : Mettre a jour les mots cles de l etape et eventuellement
290           le concept produit si reuse suite à la disparition du concept sd
291           Seuls les mots cles simples MCSIMP font un traitement autre
292           que de transmettre aux fils
293       """
294       #print "delete_concept",sd
295       I_ETAPE.ETAPE.delete_concept(self,sd)
296       for etape in self.etapes:
297          etape.delete_concept(sd)
298
299   def replace_concept(self,old_sd,sd):
300       """
301           Fonction : Mettre a jour les mots cles de l etape et le concept produit si reuse 
302           suite au remplacement  du concept old_sd par sd
303       """
304       #print "replace_concept",old_sd,sd
305       I_ETAPE.ETAPE.replace_concept(self,old_sd,sd)
306       for etape in self.etapes:
307          etape.replace_concept(old_sd,sd)
308          
309   def change_fichier_init(self,new_fic,text):
310     """
311        Tente de changer le fichier include. Le precedent include est conservé
312        dans old_xxx
313     """
314     if not hasattr(self,'fichier_ini'):
315        self.fichier_ini=None
316        self.fichier_text=None
317        self.fichier_err="Le fichier n'est pas defini"
318        self.contexte_fichier_init={}
319        self.recorded_units={}
320        self.jdc_aux=None
321        self.fichier_unite="PasDefini"
322        import Extensions.jdc_include
323        self.JdC_aux=Extensions.jdc_include.JdC_include
324
325     self.old_fic = self.fichier_ini
326     self.old_text = self.fichier_text
327     self.old_err = self.fichier_err
328     self.old_context=self.contexte_fichier_init
329     self.old_units=self.recorded_units
330     self.old_etapes=self.etapes
331     self.old_jdc_aux=self.jdc_aux
332
333     self.fichier_ini = new_fic
334     self.fichier_text=text
335
336     try:
337        self.make_contexte_include(new_fic,text)
338     except:
339        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
340        self.fichier_err=string.join(l)
341        raise
342
343     # L'evaluation de text dans un JDC auxiliaire s'est bien passé
344     # on peut poursuivre le traitement
345     self.init_modif()
346     self.state="undetermined"
347     self.fichier_err=None
348     # On enregistre la modification de fichier
349     self.record_unite()
350     # Le contexte du parent doit etre reinitialise car les concepts produits ont changé
351     self.parent.reset_context()
352
353     # Si des concepts ont disparu lors du changement de fichier, on demande leur suppression
354     self.old_contexte_fichier_init=self.old_context
355     self.reevalue_sd_jdc()
356
357     self.fin_modif()
358
359   def restore_fichier_init(self):
360     """
361        Restaure le fichier init enregistre dans old_xxx
362     """
363     self.fichier_ini=self.old_fic
364     self.fichier_text=self.old_text
365     self.fichier_err=self.old_err
366     self.contexte_fichier_init=self.old_context
367     self.recorded_units=self.old_units
368     self.etapes=self.old_etapes
369     self.jdc_aux=self.old_jdc_aux
370
371   def force_fichier_init(self):
372     """
373        Force le fichier init en erreur
374     """
375     j_context=self.jdc_aux.get_contexte_avant(None)
376     # On remplit le dictionnaire des concepts produits inclus
377     # en retirant les concepts présents dans le  contexte initial
378     # On ajoute egalement le concept produit dans le sds_dict du parent
379     # sans verification car on est sur (verification integrée) que
380     # le nommage est possible
381     self.g_context.clear()
382     context_ini=self.jdc_aux.context_ini
383     for k,v in j_context.items():
384        if not context_ini.has_key(k) or context_ini[k] != v:
385            self.g_context[k]=v
386            self.parent.sds_dict[k]=v
387     # On recupere le contexte courant
388     self.current_context=self.jdc_aux.current_context
389     self.index_etape_courante=self.jdc_aux.index_etape_courante
390     self.contexte_fichier_init = j_context
391
392     # On conserve la memoire du nouveau fichier
393     # mais on n'utilise pas les concepts crees par ce fichier
394     # on met l'etape en erreur : fichier_err=string.join(l)
395     self.init_modif()
396     self.state="undetermined"
397     # On enregistre la modification de fichier
398     self.record_unite()
399     #self.etapes=[]
400     #self.g_context={}
401     # Le contexte du parent doit etre reinitialise car les concepts produits ont changé
402     self.parent.reset_context()
403
404     self.old_contexte_fichier_init=self.old_context
405     #self.contexte_fichier_init={}
406     self.reevalue_sd_jdc()
407     self.fin_modif()
408
409     self.jdc_aux.force_contexte(self.g_context)
410
411
412   def make_contexte_include(self,fichier,text):
413     """
414         Cette méthode sert à créer un contexte en interprétant un texte source
415         Python
416     """
417     #print "make_contexte_include"
418     # on récupère le contexte d'un nouveau jdc dans lequel on interprete text
419     contexte = self.get_contexte_jdc(fichier,text)
420     if contexte == None :
421       raise Exception("Impossible de construire le jeu de commandes correspondant au fichier")
422     else:
423       # Pour les macros de type include : INCLUDE, INCLUDE_MATERIAU et POURSUITE
424       # l'attribut g_context est un dictionnaire qui contient les concepts produits par inclusion
425       # l'attribut contexte_fichier_init est un dictionnaire qui contient les concepts produits
426       # en sortie de macro. g_context est obtenu en retirant de contexte_fichier_init les concepts
427       # existants en debut de macro contenus dans context_ini (dans get_contexte_jdc)
428       # g_context est utilisé pour avoir les concepts produits par la macro
429       # contexte_fichier_init est utilisé pour avoir les concepts supprimés par la macro
430       self.contexte_fichier_init = contexte
431
432   def reevalue_fichier_init_OBSOLETE(self):
433       """Recalcule les concepts produits par le fichier enregistre"""
434       #print "reevalue_fichier_init"
435       old_context=self.contexte_fichier_init
436       try:
437          self.make_contexte_include(self.fichier_ini ,self.fichier_text)
438       except:
439          l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
440          self.fichier_err = string.join(l)
441          #self.etapes=[]
442          self.g_context={}
443
444          self.old_contexte_fichier_init=old_context
445          self.contexte_fichier_init={}
446          self.reevalue_sd_jdc()
447          return
448
449       # L'evaluation s'est bien passee
450       self.fichier_err = None
451       self.old_contexte_fichier_init=old_context
452       self.reevalue_sd_jdc()
453       #print "reevalue_fichier_init",self.jdc_aux.context_ini
454
455   def update_fichier_init(self,unite):
456       """Reevalue le fichier init sans demander (dans la mesure du possible) a l'utilisateur 
457          les noms des fichiers
458          Ceci suppose que les relations entre unites et noms ont été memorisees préalablement
459       """
460       #print "update_fichier_init",unite
461       self.fichier_err=None
462       self.old_contexte_fichier_init=self.contexte_fichier_init
463       old_fichier_ini=self.fichier_ini
464
465       #print "update_fichier_init",self,self.parent,self.parent.recorded_units
466
467       #if unite != self.fichier_unite or not self.parent.recorded_units.has_key(unite):
468       if not self.parent.recorded_units.has_key(unite):
469          # Nouvelle unite
470          f,text=self.get_file(unite=unite,fic_origine=self.parent.nom)
471          units={}
472          if f is not None:
473             self.fichier_ini = f
474             self.fichier_text=text
475          self.recorded_units=units
476          if self.fichier_ini is None and self.jdc.appli:
477             self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
478                      message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
479       else:
480          # Unite existante
481          f,text,units=self.parent.recorded_units[unite]
482          self.fichier_ini = f
483          self.fichier_text=text
484          self.recorded_units=units
485
486       if self.fichier_ini is None:
487          # Le fichier n'est pas défini
488          self.fichier_err="Le fichier associé n'est pas défini"
489          self.parent.change_unit(unite,self,self.fichier_unite)
490          self.g_context={}
491          self.contexte_fichier_init={}
492          self.parent.reset_context()
493          self.reevalue_sd_jdc()
494          return
495
496       if old_fichier_ini == self.fichier_ini:
497          # Le fichier inclus n'a pas changé. On ne recrée pas le contexte
498          #print "update_fichier_init.fichier inchange",self.jdc_aux.context_ini
499          return
500
501       try:
502         self.make_contexte_include(self.fichier_ini,self.fichier_text)
503         # Les 3 attributs fichier_ini fichier_text recorded_units doivent etre corrects
504         # avant d'appeler change_unit
505         self.parent.change_unit(unite,self,self.fichier_unite)
506       except:
507         # Erreurs lors de l'evaluation de text dans un JDC auxiliaire
508         l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
509         # On conserve la memoire du nouveau fichier
510         # mais on n'utilise pas les concepts crees par ce fichier
511         # on met l'etape en erreur : fichier_err=string.join(l)
512         self.fichier_err=string.join(l)
513         self.parent.change_unit(unite,self,self.fichier_unite)
514         self.g_context={}
515         self.contexte_fichier_init={}
516
517       # Le contexte du parent doit etre reinitialise car les concepts 
518       # produits ont changé
519       self.parent.reset_context()
520       # Si des concepts ont disparu lors du changement de fichier, on 
521       # demande leur suppression
522       self.reevalue_sd_jdc()
523       #print "update_fichier_init",self.jdc_aux.context_ini
524
525   def record_unite(self):
526       if self.nom == "POURSUITE":
527          self.parent.record_unit(None,self)
528       else:
529          if hasattr(self,'fichier_unite') : 
530             self.parent.record_unit(self.fichier_unite,self)
531
532   def get_file_memo(self,unite=None,fic_origine=''):
533       """Retourne le nom du fichier et le source correspondant a l'unite unite
534          Initialise en plus recorded_units
535       """
536       #print "get_file_memo",unite,fic_origine,self,self.parent
537       #print self.parent.old_recorded_units
538       #print self.parent.recorded_units
539       if unite is None:
540          units={}
541       else:
542          units=self.parent.recorded_units
543       if self.parent.old_recorded_units.has_key(unite):
544          f,text,units=self.parent.old_recorded_units[unite]
545          #print id(self.recorded_units)
546          self.recorded_units=units
547          #print id(self.recorded_units)
548          return f,text
549       elif self.jdc :
550          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
551       else:
552          f,text=None,None
553       self.recorded_units=units
554       if f is None and self.jdc.appli:
555          self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
556                           message="Ce fichier ne sera pas pris en compte\n"+"Le fichier associé n'est pas défini")
557       return f,text
558
559 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
560   def get_file(self,unite=None,fic_origine=''):
561       """Retourne le nom du fichier et le source correspondant a l'unite unite
562          Initialise en plus recorded_units
563       """
564       #print "get_file",unite
565       units={}
566       if self.jdc :
567          f,text=self.jdc.get_file(unite=unite,fic_origine=fic_origine)
568       else:
569          f,text=None,None
570       self.recorded_units=units
571       return f,text
572
573 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
574   def make_include(self,unite=None):
575       """
576           Inclut un fichier dont l'unite logique est unite
577           Cette methode est appelee par la fonction sd_prod de la macro INCLUDE
578           Si l'INCLUDE est invalide, la methode doit produire une exception 
579           Sinon on retourne None. Les concepts produits par l'INCLUDE sont
580           pris en compte par le JDC parent lors du calcul du contexte (appel de ???)
581       """
582       #print "make_include",unite
583       # On supprime l'attribut unite qui bloque l'evaluation du source de l'INCLUDE
584       # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
585       del self.unite
586       # Si unite n'a pas de valeur, l'etape est forcement invalide. On peut retourner None
587       if not unite : return
588
589       if not hasattr(self,'fichier_ini') : 
590          # Si le fichier n'est pas defini on le demande
591          f,text=self.get_file_memo(unite=unite,fic_origine=self.parent.nom)
592          # On memorise le fichier retourne
593          self.fichier_ini  = f
594          self.fichier_text = text
595          self.contexte_fichier_init={}
596          self.fichier_unite=unite
597          self.fichier_err=None
598          try:
599            import Extensions.jdc_include
600          except:
601            traceback.print_exc()
602            raise
603          self.JdC_aux=Extensions.jdc_include.JdC_include
604
605          if f is None:
606              self.fichier_err="Le fichier INCLUDE n est pas defini"
607              self.parent.record_unit(unite,self)
608              raise Exception(self.fichier_err)
609
610          try:
611            self.make_contexte_include(self.fichier_ini ,self.fichier_text)
612            self.parent.record_unit(unite,self)
613            #print "make_include.context_ini",self.jdc_aux.context_ini
614          except:
615            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
616            if self.jdc.appli:
617               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier inclus",
618                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
619                                            )
620            self.parent.record_unit(unite,self)
621            self.g_context={}
622            self.fichier_err = string.join(l)
623            self.contexte_fichier_init={}
624            raise
625
626       else:
627          # Si le fichier est deja defini on ne reevalue pas le fichier
628          # et on leve une exception si une erreur a été enregistrée
629          self.update_fichier_init(unite)
630          self.fichier_unite=unite
631          if self.fichier_err is not None: raise Exception(self.fichier_err)
632         
633
634 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
635   def make_contexte(self,fichier,text):
636     """
637         Cette méthode sert à créer un contexte pour INCLUDE_MATERIAU
638         en interprétant un texte source Python
639         Elle est appelee par la fonction sd_prd d'INCLUDE_MATERIAU
640     """
641     # On supprime l'attribut mat qui bloque l'evaluation du source de l'INCLUDE_MATERIAU
642     # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini
643     if hasattr(self,'mat'):del self.mat
644     self.fichier_ini =fichier
645     self.fichier_unite =fichier
646     self.fichier_text=text
647     self.fichier_err=None 
648     self.contexte_fichier_init={}
649     # On specifie la classe a utiliser pour le JDC auxiliaire
650     try:
651       import Extensions.jdc_include
652     except:
653       traceback.print_exc()
654       raise
655     self.JdC_aux=Extensions.jdc_include.JdC_include
656     try:
657        self.make_contexte_include(self.fichier_ini ,self.fichier_text)
658        self.parent.record_unit(self.fichier_unite,self)
659     except:
660        l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
661        self.fichier_err = string.join(l)
662        self.parent.record_unit(self.fichier_unite,self)
663        self.g_context={}
664        self.contexte_fichier_init={}
665        raise
666
667 #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro)
668   def update_sdprod(self,cr='non'):
669      # Cette methode peut etre appelee dans EFICAS avec des mots cles de 
670      # la commande modifies. Ceci peut conduire a la construction ou
671      # a la reconstruction d'etapes dans le cas d'INCLUDE ou d'INCLUDE_MATERIAU
672      # Il faut donc positionner le current_step avant l'appel
673      CONTEXT.unset_current_step()
674      CONTEXT.set_current_step(self)
675      valid=Validation.V_MACRO_ETAPE.MACRO_ETAPE.update_sdprod(self,cr=cr)
676      CONTEXT.unset_current_step()
677      return valid
678
679 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
680   def Build_sd(self,nom):
681       """
682            Methode de Noyau surchargee pour poursuivre malgre tout
683            si une erreur se produit pendant la creation du concept produit
684       """
685       try:
686          sd=Noyau.N_MACRO_ETAPE.MACRO_ETAPE.Build_sd(self,nom)
687       except AsException,e:
688          # Une erreur s'est produite lors de la construction du concept
689          # Comme on est dans EFICAS, on essaie de poursuivre quand meme
690          # Si on poursuit, on a le choix entre deux possibilités :
691          # 1. on annule la sd associée à self
692          # 2. on la conserve mais il faut la retourner
693          # On choisit de l'annuler
694          # En plus il faut rendre coherents sdnom et sd.nom
695          self.sd=None
696          self.sdnom=None
697          self.state="unchanged"
698          self.valid=0
699
700       return self.sd
701
702 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
703   def make_poursuite(self):
704       """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE
705       """
706       #print "make_poursuite"
707       if not hasattr(self,'fichier_ini') :
708          # Si le fichier n'est pas defini on le demande
709          f,text=self.get_file_memo(fic_origine=self.parent.nom)
710          # On memorise le fichier retourne
711          self.fichier_ini = f
712          self.fichier_unite = None
713          self.fichier_text = text
714          self.fichier_err=None
715          try:
716            import Extensions.jdc_include
717          except:
718            traceback.print_exc()
719            raise
720          self.JdC_aux=Extensions.jdc_include.JdC_poursuite
721          self.contexte_fichier_init={}
722
723          if f is None:
724              self.fichier_err="Le fichier POURSUITE n'est pas defini"
725              self.parent.record_unit(None,self)
726              raise Exception(self.fichier_err)
727
728          try:
729            self.make_contexte_include(self.fichier_ini,self.fichier_text)
730            self.parent.record_unit(None,self)
731          except:
732            l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1])
733            if self.jdc.appli:
734               self.jdc.appli.affiche_alerte("Erreur lors de l'evaluation du fichier poursuite",
735                                             message="Ce fichier ne sera pas pris en compte\n"+string.join(l)
736                                            )
737            self.parent.record_unit(None,self)
738            self.g_context={}
739            self.fichier_err = string.join(l)
740            self.contexte_fichier_init={}
741            raise
742
743       else:
744          # Si le fichier est deja defini on ne reevalue pas le fichier
745          # et on leve une exception si une erreur a été enregistrée
746          self.update_fichier_init(None)
747          if self.fichier_err is not None: raise Exception(self.fichier_err)
748
749 #ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro 
750   def type_sdprod(self,co,t):
751       """
752            Cette methode a pour fonction de typer le concept co avec le type t
753             dans les conditions suivantes
754             1- co est un concept produit de self
755             2- co est un concept libre : on le type et on l attribue à self
756            Elle enregistre egalement les concepts produits (on fait l hypothese
757             que la liste sdprods a été correctement initialisee, vide probablement)
758       """
759       #print "type_sdprod",co,t
760       if not hasattr(co,'etape'):
761          # Le concept vaut None probablement. On ignore l'appel
762          return
763       #
764       # On cherche a discriminer les differents cas de typage d'un concept
765       # produit par une macro qui est specifie dans un mot cle simple.
766       # On peut passer plusieurs fois par type_sdprod ce qui explique
767       # le nombre important de cas.
768       #
769       # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom)
770       # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod.
771       #         Cas semblable a Cas 1.
772       # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere
773       #         la propriete du concept de la macro parent a la macro courante (self)
774       #         en verifiant que le type est valide
775       # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est
776       #         deja passe par type_sdprod et que la propriete a ete transfere a une
777       #         etape fille. Cas semblable a Cas 3.
778       # Cas 5 : Le concept est produit par une etape externe a la macro.
779       #
780       if co.etape == None:
781          # Cas 1 : le concept est libre
782          # On l'attache a la macro et on change son type dans le type demande
783          # Recherche du mot cle simple associe au concept
784          mcs=self.get_mcs_with_co(co)
785          if len(mcs) != 1:
786             raise AsException("""Erreur interne.
787 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
788          mcs=mcs[0]
789          #
790          # Attention : la seule modif est ici : Accas.CO au lieu de CO
791          #
792          if not Accas.CO in mcs.definition.type:
793             raise AsException("""Erreur interne.
794 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
795          co.etape=self
796          co.__class__ = t
797          self.sdprods.append(co)
798
799       elif co.etape== self:
800          # Cas 2 : le concept est produit par la macro (self)
801          # On est deja passe par type_sdprod (Cas 1 ou 3).
802          # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
803          # Le type du concept doit etre coherent avec le type demande (seulement derive)
804          if not isinstance(co,t):
805             raise AsException("""Erreur interne.
806 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
807          self.sdprods.append(co)
808
809       elif co.etape== self.parent:
810          # Cas 3 : le concept est produit par la macro parente (self.parent)
811          # on transfere la propriete du concept a la macro fille
812          # et on change le type du concept comme demande
813          # Au prealable, on verifie que le concept existant (co) est une instance
814          # possible du type demande (t)
815          # Cette règle est normalement cohérente avec les règles de vérification des mots-clés
816          if not isinstance(co,t):
817             raise AsException("""
818 Impossible de changer le type du concept produit (%s) en (%s).
819 Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co,t,co.__class__,t))
820          mcs=self.get_mcs_with_co(co)
821          if len(mcs) != 1:
822             raise AsException("""Erreur interne.
823 Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co)
824          mcs=mcs[0]
825          if not Accas.CO in mcs.definition.type:
826             raise AsException("""Erreur interne.
827 Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type))
828          co.etape=self
829          # On ne change pas le type car il respecte la condition isinstance(co,t)
830          #co.__class__ = t
831          self.sdprods.append(co)
832
833       elif self.issubstep(co.etape):
834          # Cas 4 : Le concept est propriété d'une sous etape de la macro (self).
835          # On est deja passe par type_sdprod (Cas 3 ou 1).
836          # Il suffit de le mettre dans la liste des concepts produits (self.sdprods)
837          # Le type du concept et t doivent etre derives.
838          # Il n'y a aucune raison pour que la condition ne soit pas verifiee.
839          if not isinstance(co,t):
840             raise AsException("""Erreur interne.
841 Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__))
842          self.sdprods.append(co)
843
844       else:
845          # Cas 5 : le concept est produit par une autre étape
846          # On ne fait rien
847          return
848