Salome HOME
F.R: composimp.py : dans méthode select_in_file, ajout d'un paramètre manquant dans le
[tools/eficas.git] / Ihm / I_JDC.py
1 """
2 """
3 # Modules Python
4 import types,traceback
5 import string,linecache
6
7 # Modules Eficas
8 import I_OBJECT
9 from Noyau.N_ASSD import ASSD
10 from Noyau.N_ETAPE import ETAPE
11 from Noyau.N_Exception import AsException
12 from Extensions import commentaire,parametre,parametre_eval
13
14 class JDC(I_OBJECT.OBJECT):
15    """
16    """
17    def __init__(self):
18       self.editmode=0
19       self.etapes_niveaux=[]
20       self.niveau=self
21       self.params=[]
22       self.fonctions=[]
23       self._etape_context=None
24
25    def get_cmd(self,nomcmd):
26       """
27           Retourne l'objet de type COMMANDE de nom nomcmd
28       """
29       for cata in self.cata:
30          if hasattr(cata,nomcmd):
31             return getattr(cata,nomcmd)
32
33    def get_sd_avant_du_bon_type(self,etape,types_permis):
34       """
35           Retourne la liste des concepts avant etape d'un type acceptable
36       """
37       d=self.get_contexte_avant(etape)
38       l=[]
39       for k,v in d.items():
40         if type(v) != types.InstanceType : continue
41         # On considère que seul assd indique un type quelconque pas CO
42         elif self.assd in types_permis :
43            l.append(k)
44         elif self.est_permis(v,types_permis):
45            l.append(k)
46       l.sort()
47       return l
48
49    def est_permis(self,v,types_permis):
50       for type_ok in types_permis:
51           if type_ok in ('R','I','C','TXM') and v in self.params : 
52              return 1
53           elif type_ok == 'R' and v.__class__.__name__ == 'reel' : 
54              return 1
55           elif type_ok == 'I' and v.__class__.__name__ == 'entier' : 
56              return 1
57           elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : 
58              return 1
59           elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : 
60              return 1
61           elif type(type_ok) != types.ClassType : 
62              continue
63           elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
64              return 1
65       return 0
66
67    def addentite(self,name,pos):
68       """
69           Ajoute une entite :
70           Si name est le nom d une commande ou un commentaire ajoute 
71           une etape au JDC
72           Sinon remonte une erreur
73       """
74       self.init_modif()
75       self.editmode=1
76       if name == "COMMENTAIRE" :
77         # ajout d'un commentaire
78         self.set_current_step()
79         ind = 1
80         for child in self.etapes :
81           if isinstance(child,commentaire.COMMENTAIRE):
82             ind = ind+1
83         objet = commentaire.COMMENTAIRE('',parent=self)
84         objet.nom = "_comm_"+`ind`
85         if pos == None : pos = 0
86         self.etapes.insert(pos,objet)
87         self.editmode=0
88         self.active_etapes()
89         return objet
90       elif name == "PARAMETRE":
91         # ajout d'un parametre
92         self.set_current_step()
93         nom_param = '_param_'+str(len(self.params)+1)
94         objet = parametre.PARAMETRE(nom=nom_param)
95         if pos == None : pos = 0
96         self.etapes.insert(pos,objet)
97         self.editmode=0
98         self.reset_context()
99         self.active_etapes()
100         return objet
101       elif name == "PARAMETRE_EVAL":
102         # ajout d'un parametre EVAL
103         self.set_current_step()
104         nom_param = '_param_'+str(len(self.params)+1)
105         objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
106         if pos == None : pos = 0
107         self.etapes.insert(pos,objet)
108         self.editmode=0
109         self.reset_context()
110         self.active_etapes()
111         return objet
112       elif type(name)==types.InstanceType:
113         # on est dans le cas où on veut ajouter une commande déjà 
114         # existante (par copie donc)
115         # on est donc nécessairement en mode editeur ...
116         objet = name
117         # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
118         objet.reparent(self)
119         self.set_current_step()
120         if isinstance(objet,ETAPE):
121           if objet.nom_niveau_definition == 'JDC':
122             # l'objet dépend directement du JDC
123             objet.niveau = self
124           else:
125             # l'étape dépend d'un niveau et non directement du JDC :
126             # il faut l'enregistrer dans le niveau de parent
127             objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
128             objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
129         self.etapes.insert(pos,objet)
130         # il faut vérifier que les concepts utilisés par objet existent bien
131         # à ce niveau d'arborescence
132         objet.verif_existence_sd()
133         self.active_etapes()
134         self.editmode=0
135         self.reset_context()
136         return objet
137       else :
138         # On veut ajouter une nouvelle commande
139         try:
140           self.set_current_step()
141           cmd=self.get_cmd(name)
142           # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
143           # auprès du step courant car editmode vaut 1
144           # Par contre elle a le bon parent grace a set_current_step
145           e=cmd.make_objet()
146           if pos == None : pos = 0
147           self.etapes.insert(pos,e)
148           self.reset_current_step()
149           self.editmode=0
150           self.reset_context()
151           self.active_etapes()
152           return e
153         except:
154           traceback.print_exc()
155           self.reset_current_step()
156           self.editmode=0
157           raise AsException("Impossible d ajouter la commande "+name)
158
159    def set_current_step(self):
160       CONTEXT.unset_current_step()
161       CONTEXT.set_current_step(self)
162
163    def reset_current_step(self):
164       CONTEXT.unset_current_step()
165
166    def liste_mc_presents(self):
167       return []
168
169    def get_sd_avant_etape(self,nom_sd,etape):
170       return self.get_contexte_avant(etape).get(nom_sd,None)
171
172    def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
173       """ 
174            Cette méthode retourne la SD de nom nom_sd qui est éventuellement
175             définie apres etape 
176            Si avec vaut 'non' exclut etape de la recherche
177       """
178       ietap=self.etapes.index(etape)
179       if avec == 'non':ietap=ietap+1
180       for e in self.etapes[ietap:]:
181         sd=e.get_sdprods(nom_sd)
182         if sd:
183           if hasattr(e,'reuse'):
184             if e.reuse != sd:
185               return sd
186       return None
187
188    def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
189       """
190            Fonction: retourne la SD de nom nom_sd qui est éventuellement
191             définie avant ou apres etape
192            Permet de vérifier si un concept de meme nom existe dans le périmètre 
193            d'une étape
194            Si avec vaut 'non' exclut etape de la recherche
195       """
196       sd=self.get_sd_avant_etape(nom_sd,etape)
197       if sd:return sd
198       return self.get_sd_apres_etape(nom_sd,etape,avec)
199
200    def active_etapes(self):
201       """
202           Cette méthode a pour fonction de désactiver les étapes qui doivent
203           l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas 
204           comprises entre le premier DEBUT/POURSUITE et le premier FIN 
205           et rendre actives les autres
206       """
207       if self.definition.code == 'ASTER' :
208          # Seulement pour ASTER :
209          # Avant DEBUT actif vaut 0
210          # Apres DEBUT et avant le 1er FIN actif vaut 1
211          # Apres le 1er FIN actif vaut -1
212          actif=0
213       else:
214          actif=1
215       for etape in self.etapes:
216         if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
217         if actif == 1:
218            etape.active()
219         else:
220            etape.inactive()
221         if etape.nom == 'FIN':actif=-1
222
223    def suppentite(self,etape) :
224       """  
225           Cette methode a pour fonction de supprimer une étape dans 
226           un jeu de commandes
227       """
228       self.init_modif()
229       self.etapes.remove(etape)
230       if etape.niveau is not self:
231         # Dans ce cas l'étape est enregistrée dans un niveau
232         # Il faut la désenregistrer
233         etape.niveau.unregister(etape)
234       etape.supprime_sdprods()
235       self.active_etapes()
236
237    def del_sdprod(self,sd):
238       """
239           Supprime la SD sd de la liste des sd et des dictionnaires de contexte
240       """
241       if sd in self.sds : self.sds.remove(sd)
242       if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
243
244    def delete_concept(self,sd):
245       """ 
246           Inputs :
247              sd=concept detruit
248           Fonction :
249              Mettre a jour les etapes du JDC suite à la disparition du 
250              concept sd
251              Seuls les mots cles simples MCSIMP font un traitement autre 
252              que de transmettre aux fils
253       """
254       for etape in self.etapes :
255         etape.delete_concept(sd)
256
257    def analyse(self):
258       self.compile()
259       if not self.cr.estvide():return
260       self.exec_compile()
261       self.active_etapes()
262
263    def register(self,etape):
264       """ 
265            Cette méthode ajoute  etape dans la liste
266            des etapes self.etapes et retourne l identificateur d'étape
267            fourni par l appel a g_register
268            A quoi sert editmode ?
269            - Si editmode vaut 1, on est en mode edition de JDC. On cherche 
270            à enregistrer une étape que l'on a créée avec eficas (en passant 
271            par addentite) auquel cas on ne veut récupérer que son numéro 
272            d'enregistrement et c'est addentité qui l'enregistre dans 
273            self.etapes à la bonne place...
274            - Si editmode vaut 0, on est en mode relecture d'un fichier de 
275            commandes et on doit enregistrer l'étape à la fin de self.etapes 
276            (dans ce cas l'ordre des étapes est bien l'ordre chronologique 
277            de leur création   )
278       """
279       if not self.editmode:
280          self.etapes.append(etape)
281       else:
282          pass
283       return self.g_register(etape)
284
285    def register_parametre(self,param):
286       """
287           Cette méthode sert à ajouter un paramètre dans la liste des paramètres
288       """
289       self.params.append(param)
290
291    def register_fonction(self,fonction):
292       """
293           Cette méthode sert à ajouter une fonction dans la liste des fonctions
294       """
295       self.fonctions.append(fonction)
296
297    def delete_param(self,param):
298       """
299           Supprime le paramètre param de la liste des paramètres
300           et du contexte gobal
301       """
302       if param in self.params : self.params.remove(param)
303       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
304
305    def get_parametres_fonctions_avant_etape(self,etape):
306       """
307           Retourne deux éléments :
308           - une liste contenant les noms des paramètres (constantes ou EVAL) 
309             définis avant etape
310           - une liste contenant les formules définies avant etape
311       """
312       l_constantes = []
313       l_fonctions = []
314       # on récupère le contexte avant etape
315       # on ne peut mettre dans les deux listes que des éléments de ce contexte
316       d=self.get_contexte_avant(etape)
317       # construction de l_constantes
318       for param in self.params:
319         nom = param.nom
320         if not nom : continue
321         if d.has_key(nom): l_constantes.append(nom)
322       # construction de l_fonctions
323       for form in self.fonctions:
324         nom = form.nom
325         if not nom : continue
326         if d.has_key(nom): l_fonctions.append(form.get_formule())
327
328       # on ajoute les concepts produits par DEFI_VALEUR
329       # XXX On pourrait peut etre faire plutot le test sur le type
330       # de concept : entier, reel, complexe, etc.
331       for k,v in d.items():
332          if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
333             l_constantes.append(k)
334
335       # on retourne les deux listes
336       return l_constantes,l_fonctions
337
338    def get_nb_etapes_avant(self,niveau):
339       """ 
340           Retourne le nombre d etapes avant le debut de niveau
341       """
342       nb=0
343       for niv in self.etapes_niveaux:
344         if niv == niveau:break
345         nb=nb+len(niv.etapes)
346       return nb
347
348    def send_message(self,message):
349       if self.appli:
350          self.appli.send_message(message)
351
352 #XXX ne semble pas servir pour JDC
353 #   def reevalue_sd_jdc(self):
354       #""" 
355           #Avec la liste des SD qui ont été supprimées, propage la disparition de ces
356           #SD dans toutes les étapes et descendants
357       #"""
358       #l_sd = self.diff_contextes()
359       #if len(l_sd) == 0 : return
360       #for sd in l_sd:
361         #self.jdc.delete_concept(sd)
362
363    def init_modif(self):
364       """
365       Méthode appelée au moment où une modification va être faite afin de 
366       déclencher d'éventuels traitements pré-modification
367       """
368       self.state = 'modified'
369
370    def fin_modif(self):
371       pass
372
373    def get_liste_mc_inconnus(self):
374      """
375      Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
376      """
377      # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
378      l_mc = []
379      for etape in self.etapes :
380          if etape.isactif() :
381             if not etape.isvalid() :
382                l = etape.get_liste_mc_inconnus()
383                if l : l_mc.extend(l)
384      return l_mc    
385
386    def get_file(self,unite=None,fic_origine=''):
387       """
388           Retourne le nom du fichier correspondant à un numero d'unité
389           logique (entier) ainsi que le source contenu dans le fichier
390       """
391       if self.appli :
392          # Si le JDC est relié à une application maitre, on délègue la recherche
393          file,text = self.appli.get_file(unite,fic_origine)
394       else:
395          file = None
396          if unite != None:
397             if os.path.exists("fort."+str(unite)):
398                file= "fort."+str(unite)
399          if file == None :
400             raise AsException("Impossible de trouver le fichier correspondant \
401                                a l unite %s" % unite)
402          if not os.path.exists(file):
403             raise AsException("%s n'est pas un fichier existant" % unite)
404          fproc=open(file,'r')
405          text=fproc.read()
406          fproc.close()
407       text=string.replace(text,'\r\n','\n')
408       linecache.cache[file]=0,0,string.split(text,'\n'),file
409       return file,text
410
411
412    def get_genealogie(self):
413       """
414           Retourne la liste des noms des ascendants de l'objet self
415           jusqu'à la première ETAPE parent.
416       """
417       return []
418
419    def NommerSdprod(self,sd,sdnom):
420       """
421           Nomme la SD apres avoir verifie que le nommage est possible : nom
422           non utilise
423           Si le nom est deja utilise, leve une exception
424           Met le concept créé dans le concept global g_context
425       """
426       # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
427       # Le dictionnaire g_context ne représente pas le contexte
428       # effectif avant une étape.
429       # Il faut utiliser get_contexte_avant avec une indication de l'étape
430       # traitée. Pour le moment, il n'y a pas de moyen de le faire : ajouter 
431       # un attribut dans le JDC ???
432       if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
433       if self._etape_context:
434          o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
435       else:
436          o=self.g_context.get(sdnom,None)
437       if isinstance(o,ASSD):
438          raise AsException("Nom de concept deja defini : %s" % sdnom)
439
440       # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
441       # Ajoute a la creation (appel de reg_sd).
442       self.g_context[sdnom]=sd
443       sd.nom=sdnom
444
445    def set_etape_context(self,etape):
446       """
447           Positionne l'etape qui sera utilisee dans NommerSdProd pour
448           decider si le concept passé pourra etre  nommé
449       """
450       self._etape_context=etape
451
452    def reset_context(self):
453       """ 
454           Cette methode reinitialise le contexte glissant pour pouvoir
455           tenir compte des modifications de l'utilisateur : création
456           de commandes, nommage de concepts, etc.
457       """
458       self.current_context={}
459       self.index_etape_courante=0
460
461    def del_param(self,param):
462       """
463           Supprime le paramètre param de la liste des paramètres
464           et du contexte gobal
465       """
466       if param in self.params : self.params.remove(param)
467       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
468
469    def del_fonction(self,fonction):
470       """
471           Supprime la fonction fonction de la liste des fonctions
472           et du contexte gobal
473       """
474       if fonction in self.fonctions : self.fonctions.remove(fonction)
475       if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
476