Salome HOME
CCAR: Modified Files:
[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         self.active_etapes()
131         self.editmode=0
132         self.reset_context()
133         return objet
134       else :
135         # On veut ajouter une nouvelle commande
136         try:
137           self.set_current_step()
138           cmd=self.get_cmd(name)
139           # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
140           # auprès du step courant car editmode vaut 1
141           # Par contre elle a le bon parent grace a set_current_step
142           e=cmd.make_objet()
143           if pos == None : pos = 0
144           self.etapes.insert(pos,e)
145           self.reset_current_step()
146           self.editmode=0
147           self.reset_context()
148           self.active_etapes()
149           return e
150         except:
151           traceback.print_exc()
152           self.reset_current_step()
153           self.editmode=0
154           raise AsException("Impossible d ajouter la commande "+name)
155
156    def set_current_step(self):
157       CONTEXT.unset_current_step()
158       CONTEXT.set_current_step(self)
159
160    def reset_current_step(self):
161       CONTEXT.unset_current_step()
162
163    def liste_mc_presents(self):
164       return []
165
166    def get_sd_avant_etape(self,nom_sd,etape):
167       return self.get_contexte_avant(etape).get(nom_sd,None)
168
169    def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
170       """ 
171            Cette méthode retourne la SD de nom nom_sd qui est éventuellement
172             définie apres etape 
173            Si avec vaut 'non' exclut etape de la recherche
174       """
175       ietap=self.etapes.index(etape)
176       if avec == 'non':ietap=ietap+1
177       for e in self.etapes[ietap:]:
178         sd=e.get_sdprods(nom_sd)
179         if sd:
180           if hasattr(e,'reuse'):
181             if e.reuse != sd:
182               return sd
183       return None
184
185    def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
186       """
187            Fonction: retourne la SD de nom nom_sd qui est éventuellement
188             définie avant ou apres etape
189            Permet de vérifier si un concept de meme nom existe dans le périmètre 
190            d'une étape
191            Si avec vaut 'non' exclut etape de la recherche
192       """
193       sd=self.get_sd_avant_etape(nom_sd,etape)
194       if sd:return sd
195       return self.get_sd_apres_etape(nom_sd,etape,avec)
196
197    def active_etapes(self):
198       """
199           Cette méthode a pour fonction de désactiver les étapes qui doivent
200           l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas 
201           comprises entre le premier DEBUT/POURSUITE et le premier FIN 
202           et rendre actives les autres
203       """
204       if self.definition.code == 'ASTER' :
205          # Seulement pour ASTER :
206          # Avant DEBUT actif vaut 0
207          # Apres DEBUT et avant le 1er FIN actif vaut 1
208          # Apres le 1er FIN actif vaut -1
209          actif=0
210       else:
211          actif=1
212       for etape in self.etapes:
213         if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
214         if actif == 1:
215            etape.active()
216         else:
217            etape.inactive()
218         if etape.nom == 'FIN':actif=-1
219
220    def suppentite(self,etape) :
221       """  
222           Cette methode a pour fonction de supprimer une étape dans 
223           un jeu de commandes
224       """
225       self.init_modif()
226       self.etapes.remove(etape)
227       if etape.niveau is not self:
228         # Dans ce cas l'étape est enregistrée dans un niveau
229         # Il faut la désenregistrer
230         etape.niveau.unregister(etape)
231       etape.supprime_sdprods()
232       self.active_etapes()
233
234    def del_sdprod(self,sd):
235       """
236           Supprime la SD sd de la liste des sd et des dictionnaires de contexte
237       """
238       if sd in self.sds : self.sds.remove(sd)
239       if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
240
241    def delete_concept(self,sd):
242       """ 
243           Inputs :
244              sd=concept detruit
245           Fonction :
246              Mettre a jour les etapes du JDC suite à la disparition du 
247              concept sd
248              Seuls les mots cles simples MCSIMP font un traitement autre 
249              que de transmettre aux fils
250       """
251       for etape in self.etapes :
252         etape.delete_concept(sd)
253
254    def analyse(self):
255       self.compile()
256       if not self.cr.estvide():return
257       self.exec_compile()
258       self.active_etapes()
259
260    def register(self,etape):
261       """ 
262            Cette méthode ajoute  etape dans la liste
263            des etapes self.etapes et retourne l identificateur d'étape
264            fourni par l appel a g_register
265            A quoi sert editmode ?
266            - Si editmode vaut 1, on est en mode edition de JDC. On cherche 
267            à enregistrer une étape que l'on a créée avec eficas (en passant 
268            par addentite) auquel cas on ne veut récupérer que son numéro 
269            d'enregistrement et c'est addentité qui l'enregistre dans 
270            self.etapes à la bonne place...
271            - Si editmode vaut 0, on est en mode relecture d'un fichier de 
272            commandes et on doit enregistrer l'étape à la fin de self.etapes 
273            (dans ce cas l'ordre des étapes est bien l'ordre chronologique 
274            de leur création   )
275       """
276       if not self.editmode:
277          self.etapes.append(etape)
278       else:
279          pass
280       return self.g_register(etape)
281
282    def register_parametre(self,param):
283       """
284           Cette méthode sert à ajouter un paramètre dans la liste des paramètres
285       """
286       self.params.append(param)
287
288    def register_fonction(self,fonction):
289       """
290           Cette méthode sert à ajouter une fonction dans la liste des fonctions
291       """
292       self.fonctions.append(fonction)
293
294    def delete_param(self,param):
295       """
296           Supprime le paramètre param de la liste des paramètres
297           et du contexte gobal
298       """
299       if param in self.params : self.params.remove(param)
300       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
301
302    def get_parametres_fonctions_avant_etape(self,etape):
303       """
304           Retourne deux éléments :
305           - une liste contenant les noms des paramètres (constantes ou EVAL) 
306             définis avant etape
307           - une liste contenant les formules définies avant etape
308       """
309       l_constantes = []
310       l_fonctions = []
311       # on récupère le contexte avant etape
312       # on ne peut mettre dans les deux listes que des éléments de ce contexte
313       d=self.get_contexte_avant(etape)
314       # construction de l_constantes
315       for param in self.params:
316         nom = param.nom
317         if not nom : continue
318         if d.has_key(nom): l_constantes.append(nom)
319       # construction de l_fonctions
320       for form in self.fonctions:
321         nom = form.nom
322         if not nom : continue
323         if d.has_key(nom): l_fonctions.append(form.get_formule())
324
325       # on ajoute les concepts produits par DEFI_VALEUR
326       # XXX On pourrait peut etre faire plutot le test sur le type
327       # de concept : entier, reel, complexe, etc.
328       for k,v in d.items():
329          if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
330             l_constantes.append(k)
331
332       # on retourne les deux listes
333       return l_constantes,l_fonctions
334
335    def get_nb_etapes_avant(self,niveau):
336       """ 
337           Retourne le nombre d etapes avant le debut de niveau
338       """
339       nb=0
340       for niv in self.etapes_niveaux:
341         if niv == niveau:break
342         nb=nb+len(niv.etapes)
343       return nb
344
345    def send_message(self,message):
346       if self.appli:
347          self.appli.send_message(message)
348
349 #XXX ne semble pas servir pour JDC
350 #   def reevalue_sd_jdc(self):
351       #""" 
352           #Avec la liste des SD qui ont été supprimées, propage la disparition de ces
353           #SD dans toutes les étapes et descendants
354       #"""
355       #l_sd = self.diff_contextes()
356       #if len(l_sd) == 0 : return
357       #for sd in l_sd:
358         #self.jdc.delete_concept(sd)
359
360    def init_modif(self):
361       """
362       Méthode appelée au moment où une modification va être faite afin de 
363       déclencher d'éventuels traitements pré-modification
364       """
365       self.state = 'modified'
366
367    def fin_modif(self):
368       pass
369
370    def get_liste_mc_inconnus(self):
371      """
372      Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
373      """
374      # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
375      l_mc = []
376      for etape in self.etapes :
377          if etape.isactif() :
378             if not etape.isvalid() :
379                l = etape.get_liste_mc_inconnus()
380                if l : l_mc.extend(l)
381      return l_mc    
382
383    def get_file(self,unite=None,fic_origine=''):
384       """
385           Retourne le nom du fichier correspondant à un numero d'unité
386           logique (entier) ainsi que le source contenu dans le fichier
387       """
388       if self.appli :
389          # Si le JDC est relié à une application maitre, on délègue la recherche
390          file,text = self.appli.get_file(unite,fic_origine)
391       else:
392          file = None
393          if unite != None:
394             if os.path.exists("fort."+str(unite)):
395                file= "fort."+str(unite)
396          if file == None :
397             raise AsException("Impossible de trouver le fichier correspondant \
398                                a l unite %s" % unite)
399          if not os.path.exists(file):
400             raise AsException("%s n'est pas un fichier existant" % unite)
401          fproc=open(file,'r')
402          text=fproc.read()
403          fproc.close()
404       text=string.replace(text,'\r\n','\n')
405       linecache.cache[file]=0,0,string.split(text,'\n'),file
406       return file,text
407
408
409    def get_genealogie(self):
410       """
411           Retourne la liste des noms des ascendants de l'objet self
412           jusqu'à la première ETAPE parent.
413       """
414       return []
415
416    def NommerSdprod(self,sd,sdnom):
417       """
418           Nomme la SD apres avoir verifie que le nommage est possible : nom
419           non utilise
420           Si le nom est deja utilise, leve une exception
421           Met le concept créé dans le concept global g_context
422       """
423       # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
424       # Le dictionnaire g_context ne représente pas le contexte
425       # effectif avant une étape.
426       # Il faut utiliser get_contexte_avant avec une indication de l'étape
427       # traitée. Pour le moment, il n'y a pas de moyen de le faire : ajouter 
428       # un attribut dans le JDC ???
429       if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
430       if self._etape_context:
431          o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
432       else:
433          o=self.g_context.get(sdnom,None)
434       if isinstance(o,ASSD):
435          raise AsException("Nom de concept deja defini : %s" % sdnom)
436
437       # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
438       # Ajoute a la creation (appel de reg_sd).
439       self.g_context[sdnom]=sd
440       sd.nom=sdnom
441
442    def set_etape_context(self,etape):
443       """
444           Positionne l'etape qui sera utilisee dans NommerSdProd pour
445           decider si le concept passé pourra etre  nommé
446       """
447       self._etape_context=etape
448
449    def reset_context(self):
450       """ 
451           Cette methode reinitialise le contexte glissant pour pouvoir
452           tenir compte des modifications de l'utilisateur : création
453           de commandes, nommage de concepts, etc.
454       """
455       self.current_context={}
456       self.index_etape_courante=0
457
458    def del_param(self,param):
459       """
460           Supprime le paramètre param de la liste des paramètres
461           et du contexte gobal
462       """
463       if param in self.params : self.params.remove(param)
464       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
465
466    def del_fonction(self,fonction):
467       """
468           Supprime la fonction fonction de la liste des fonctions
469           et du contexte gobal
470       """
471       if fonction in self.fonctions : self.fonctions.remove(fonction)
472       if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
473