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