Salome HOME
CCAR : Suppression des surcharges de methodes faites pour Eficas1.5
[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       self.recorded_units={}
44       self.old_recorded_units={}
45
46    def get_sd_avant_du_bon_type(self,etape,types_permis):
47       """
48           Retourne la liste des concepts avant etape d'un type acceptable
49       """
50       d=self.get_contexte_avant(etape)
51       l=[]
52       for k,v in d.items():
53         if type(v) != types.InstanceType : continue
54         # On considère que seul assd indique un type quelconque pas CO
55         elif self.assd in types_permis :
56            l.append(k)
57         elif self.est_permis(v,types_permis):
58            l.append(k)
59       l.sort()
60       return l
61
62    def est_permis(self,v,types_permis):
63       for type_ok in types_permis:
64           if type_ok in ('R','I','C','TXM') and v in self.params : 
65              return 1
66           elif type_ok == 'R' and v.__class__.__name__ == 'reel' : 
67              return 1
68           elif type_ok == 'I' and v.__class__.__name__ == 'entier' : 
69              return 1
70           elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : 
71              return 1
72           elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : 
73              return 1
74           elif type(type_ok) != types.ClassType : 
75              continue
76           elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
77              return 1
78       return 0
79
80    def addentite(self,name,pos):
81       """
82           Ajoute une entite :
83           Si name est le nom d une commande ou un commentaire ajoute 
84           une etape au JDC
85           Sinon remonte une erreur
86       """
87       self.init_modif()
88       self.editmode=1
89       if name == "COMMENTAIRE" :
90         # ajout d'un commentaire
91         self.set_current_step()
92         ind = 1
93         for child in self.etapes :
94           if isinstance(child,commentaire.COMMENTAIRE):
95             ind = ind+1
96         objet = commentaire.COMMENTAIRE('',parent=self)
97         objet.nom = "_comm_"+`ind`
98         if pos == None : pos = 0
99         self.etapes.insert(pos,objet)
100         self.editmode=0
101         self.active_etapes()
102         return objet
103       elif name == "PARAMETRE":
104         # ajout d'un parametre
105         self.set_current_step()
106         nom_param = '_param_'+str(len(self.params)+1)
107         objet = parametre.PARAMETRE(nom=nom_param)
108         if pos == None : pos = 0
109         self.etapes.insert(pos,objet)
110         self.editmode=0
111         self.reset_context()
112         self.active_etapes()
113         return objet
114       elif name == "PARAMETRE_EVAL":
115         # ajout d'un parametre EVAL
116         self.set_current_step()
117         nom_param = '_param_'+str(len(self.params)+1)
118         objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
119         if pos == None : pos = 0
120         self.etapes.insert(pos,objet)
121         self.editmode=0
122         self.reset_context()
123         self.active_etapes()
124         return objet
125       elif type(name)==types.InstanceType:
126         # on est dans le cas où on veut ajouter une commande déjà 
127         # existante (par copie donc)
128         # on est donc nécessairement en mode editeur ...
129         objet = name
130         # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
131         objet.reparent(self)
132         self.set_current_step()
133         if isinstance(objet,ETAPE):
134           if objet.nom_niveau_definition == 'JDC':
135             # l'objet dépend directement du JDC
136             objet.niveau = self
137           else:
138             # l'étape dépend d'un niveau et non directement du JDC :
139             # il faut l'enregistrer dans le niveau de parent
140             objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
141             objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
142         self.etapes.insert(pos,objet)
143         # il faut vérifier que les concepts utilisés par objet existent bien
144         # à ce niveau d'arborescence
145         objet.verif_existence_sd()
146         self.active_etapes()
147         self.editmode=0
148         self.reset_context()
149         return objet
150       else :
151         # On veut ajouter une nouvelle commande
152         try:
153           self.set_current_step()
154           cmd=self.get_cmd(name)
155           # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
156           # auprès du step courant car editmode vaut 1
157           # Par contre elle a le bon parent grace a set_current_step
158           e=cmd.make_objet()
159           if pos == None : pos = 0
160           self.etapes.insert(pos,e)
161           self.reset_current_step()
162           self.editmode=0
163           self.reset_context()
164           self.active_etapes()
165           return e
166         except AsException,e:
167           self.reset_current_step()
168           self.editmode=0
169           raise AsException("Impossible d ajouter la commande "+name + '\n' +str(e))
170         except:
171           traceback.print_exc()
172           self.reset_current_step()
173           self.editmode=0
174           raise AsException("Impossible d ajouter la commande "+name)
175
176    def set_current_step(self):
177       CONTEXT.unset_current_step()
178       CONTEXT.set_current_step(self)
179
180    def reset_current_step(self):
181       CONTEXT.unset_current_step()
182
183    def liste_mc_presents(self):
184       return []
185
186    def get_sd_avant_etape(self,nom_sd,etape):
187       return self.get_contexte_avant(etape).get(nom_sd,None)
188
189    def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
190       """ 
191            Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement
192            définie apres etape en tenant compte des concepts detruits
193            Si avec vaut 'non' exclut etape de la recherche
194       """
195       ietap=self.etapes.index(etape)
196       if avec == 'non':ietap=ietap+1
197       d={nom_sd:sd}
198       for e in self.etapes[ietap:]:
199          if e.isactif():
200             e.update_context(d)
201             autre_sd=d.get(nom_sd,None)
202             if autre_sd is None:
203               # Le concept a ete detruit
204               return None
205             if autre_sd is not sd :
206               # L'etape produit un concept de meme nom
207               if hasattr(e,'reuse') and e.reuse == autre_sd:
208                  # Le concept est reutilise, ce n'est pas un produit de l'etape
209                  continue
210               else:
211                  # Le concept est produit par l'etape
212                  return autre_sd
213       # On n'a rien trouve. Pas de concept de nom nom_sd
214       return None
215
216    def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
217       """ 
218            Cette méthode retourne la SD de nom nom_sd qui est éventuellement
219            définie apres etape 
220            Si avec vaut 'non' exclut etape de la recherche
221       """
222       ietap=self.etapes.index(etape)
223       if avec == 'non':ietap=ietap+1
224       for e in self.etapes[ietap:]:
225         sd=e.get_sdprods(nom_sd)
226         if sd:
227           if hasattr(e,'reuse'):
228             if e.reuse != sd:
229               return sd
230       return None
231
232    def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
233       """
234            Fonction: retourne la SD de nom nom_sd qui est éventuellement
235            définie avant ou apres etape
236            Permet de vérifier si un concept de meme nom existe dans le périmètre 
237            d'une étape
238            Si avec vaut 'non' exclut etape de la recherche
239       """
240       sd=self.get_sd_avant_etape(nom_sd,etape)
241       if sd:return sd
242       return self.get_sd_apres_etape(nom_sd,etape,avec)
243
244    def get_contexte_apres(self,etape):
245       """
246          Retourne le dictionnaire des concepts connus apres etape
247          On tient compte des commandes qui modifient le contexte
248          comme DETRUIRE ou les macros
249          Si etape == None, on retourne le contexte en fin de JDC
250       """
251       if not etape: return self.get_contexte_avant(etape)
252
253       d=self.get_contexte_avant(etape)
254       if etape.isactif():etape.update_context(d)
255       self.index_etape_courante=self.index_etape_courante+1
256       return d
257
258    def active_etapes(self):
259       """
260           Cette méthode a pour fonction de désactiver les étapes qui doivent
261           l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas 
262           comprises entre le premier DEBUT/POURSUITE et le premier FIN 
263           et rendre actives les autres
264       """
265       if self.definition.code == 'ASTER' :
266          # Seulement pour ASTER :
267          # Avant DEBUT actif vaut 0
268          # Apres DEBUT et avant le 1er FIN actif vaut 1
269          # Apres le 1er FIN actif vaut -1
270          actif=0
271       else:
272          actif=1
273       for etape in self.etapes:
274         if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
275         if actif == 1:
276            etape.active()
277         else:
278            etape.inactive()
279         if etape.nom == 'FIN':actif=-1
280
281    def suppentite(self,etape) :
282       """  
283           Cette methode a pour fonction de supprimer une étape dans 
284           un jeu de commandes
285       """
286       self.init_modif()
287       # On memorise le contexte avant l'etape a supprimer
288       d=self.get_contexte_avant(etape)
289       index_etape=self.etapes.index(etape)
290
291       self.etapes.remove(etape)
292       if etape.niveau is not self:
293         # Dans ce cas l'étape est enregistrée dans un niveau
294         # Il faut la désenregistrer
295         etape.niveau.unregister(etape)
296       etape.supprime_sdprods()
297       self.active_etapes()
298
299       # Apres suppression de l'etape il faut controler que les etapes
300       # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
301       for e in self.etapes[index_etape:]:
302          e.control_sdprods(d)
303       
304       self.reset_context()
305       self.fin_modif()
306
307    def analyse(self):
308       self.compile()
309       if not self.cr.estvide():return
310       self.exec_compile()
311       self.active_etapes()
312
313    def register_parametre(self,param):
314       """
315           Cette méthode sert à ajouter un paramètre dans la liste des paramètres
316       """
317       self.params.append(param)
318
319    def register_fonction(self,fonction):
320       """
321           Cette méthode sert à ajouter une fonction dans la liste des fonctions
322       """
323       self.fonctions.append(fonction)
324
325    def delete_param(self,param):
326       """
327           Supprime le paramètre param de la liste des paramètres
328           et du contexte gobal
329       """
330       if param in self.params : self.params.remove(param)
331       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
332
333    def get_parametres_fonctions_avant_etape(self,etape):
334       """
335           Retourne deux éléments :
336           - une liste contenant les noms des paramètres (constantes ou EVAL) 
337             définis avant etape
338           - une liste contenant les formules définies avant etape
339       """
340       l_constantes = []
341       l_fonctions = []
342       # on récupère le contexte avant etape
343       # on ne peut mettre dans les deux listes que des éléments de ce contexte
344       d=self.get_contexte_avant(etape)
345       # construction de l_constantes
346       for param in self.params:
347         nom = param.nom
348         if not nom : continue
349         if d.has_key(nom): l_constantes.append(nom)
350       # construction de l_fonctions
351       for form in self.fonctions:
352         nom = form.nom
353         if not nom : continue
354         if d.has_key(nom): l_fonctions.append(form.get_formule())
355
356       # on ajoute les concepts produits par DEFI_VALEUR
357       # XXX On pourrait peut etre faire plutot le test sur le type
358       # de concept : entier, reel, complexe, etc.
359       for k,v in d.items():
360          if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
361             l_constantes.append(k)
362
363       # on retourne les deux listes
364       return l_constantes,l_fonctions
365
366    def get_nb_etapes_avant(self,niveau):
367       """ 
368           Retourne le nombre d etapes avant le debut de niveau
369       """
370       nb=0
371       for niv in self.etapes_niveaux:
372         if niv == niveau:break
373         nb=nb+len(niv.etapes)
374       return nb
375
376    def send_message(self,message):
377       if self.appli:
378          self.appli.send_message(message)
379
380    def init_modif(self):
381       """
382       Méthode appelée au moment où une modification va être faite afin de 
383       déclencher d'éventuels traitements pré-modification
384       """
385       self.state = 'modified'
386
387    def fin_modif(self):
388       self.isvalid()
389       pass
390
391    def get_liste_mc_inconnus(self):
392      """
393      Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
394      """
395      # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
396      l_mc = []
397      for etape in self.etapes :
398          if etape.isactif() :
399             if not etape.isvalid() :
400                l = etape.get_liste_mc_inconnus()
401                if l : l_mc.extend(l)
402      return l_mc    
403
404    def get_genealogie(self):
405       """
406           Retourne la liste des noms des ascendants de l'objet self
407           jusqu'à la première ETAPE parent.
408       """
409       return []
410
411    def set_etape_context(self,etape):
412       """
413           Positionne l'etape qui sera utilisee dans NommerSdProd pour
414           decider si le concept passé pourra etre  nommé
415       """
416       self._etape_context=etape
417
418    def reset_context(self):
419       """ 
420           Cette methode reinitialise le contexte glissant pour pouvoir
421           tenir compte des modifications de l'utilisateur : création
422           de commandes, nommage de concepts, etc.
423       """
424       self.current_context={}
425       self.index_etape_courante=0
426
427    def del_sdprod(self,sd):
428       """
429           Supprime la SD sd de la liste des sd et des dictionnaires de contexte
430       """
431       if sd in self.sds : self.sds.remove(sd)
432       if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
433       if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
434
435    def del_param(self,param):
436       """
437           Supprime le paramètre param de la liste des paramètres
438           et du contexte gobal
439       """
440       if param in self.params : self.params.remove(param)
441       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
442
443    def del_fonction(self,fonction):
444       """
445           Supprime la fonction fonction de la liste des fonctions
446           et du contexte gobal
447       """
448       if fonction in self.fonctions : self.fonctions.remove(fonction)
449       if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
450
451    def append_sdprod(self,sd):
452       """
453           Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
454           même nom n'existe pas déjà
455       """
456       if sd == None or sd.nom == None:return
457
458       o=self.sds_dict.get(sd.nom,None)
459       if isinstance(o,ASSD):
460          raise AsException("Nom de concept deja defini : %s" % sd.nom)
461       self.sds_dict[sd.nom]=sd
462       self.g_context[sd.nom] = sd
463       if sd not in self.sds : self.sds.append(sd)
464
465    def append_param(self,param):
466       """
467           Ajoute le paramètre param à la liste des params
468           et au contexte global
469       """
470       # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
471       if param not in self.params : self.params.append(param)
472       self.g_context[param.nom]=param
473
474    def append_fonction(self,fonction):
475       """
476           Ajoute la fonction fonction à la liste des fonctions
477           et au contexte global
478       """
479       # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
480       if fonction not in self.fonctions : self.fonctions.append(fonction)
481       self.g_context[fonction.nom]=fonction
482
483    def delete_concept(self,sd):
484       """
485           Inputs :
486              - sd=concept detruit
487           Fonction :
488           Mettre a jour les etapes du JDC suite à la disparition du
489           concept sd
490           Seuls les mots cles simples MCSIMP font un traitement autre
491           que de transmettre aux fils
492       """
493       for etape in self.etapes :
494         etape.delete_concept(sd)
495
496    def replace_concept_after_etape(self,etape,old_sd,sd):
497       """
498           Met à jour les étapes du JDC qui sont après etape en fonction
499           du remplacement du concept sd
500       """
501       index = self.etapes.index(etape)+1
502       if index == len(self.etapes) :
503          return # etape est la dernière étape du jdc ...on ne fait rien !
504       for child in self.etapes[index:]:
505         child.replace_concept(old_sd,sd)
506
507    def dump_state(self):
508       print "dump_state"
509       print "JDC.state: ",self.state
510       for etape in self.etapes :
511          print etape.nom+".state: ",etape.state
512       
513    def change_unit(self,unit,etape,old_unit):
514       if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
515       self.record_unit(unit,etape)
516
517    def record_unit(self,unit,etape):
518       """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
519       if unit is None:
520          # Cas de POURSUITE
521          self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
522       else:
523          self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
524
525 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
526    def register(self,etape):
527       """
528            Cette méthode ajoute  etape dans la liste
529            des etapes self.etapes et retourne l identificateur d'étape
530            fourni par l appel a g_register
531
532            A quoi sert editmode ?
533               - Si editmode vaut 1, on est en mode edition de JDC. On cherche
534                 à enregistrer une étape que l'on a créée avec eficas (en passant
535                 par addentite) auquel cas on ne veut récupérer que son numéro
536                 d'enregistrement et c'est addentité qui l'enregistre dans
537                 self.etapes à la bonne place...
538               - Si editmode vaut 0, on est en mode relecture d'un fichier de
539                 commandes et on doit enregistrer l'étape à la fin de self.etapes
540                 (dans ce cas l'ordre des étapes est bien l'ordre chronologique
541                 de leur création   )
542       """
543       if not self.editmode:
544          self.etapes.append(etape)
545       else:
546          pass
547       return self.g_register(etape)
548
549 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
550    def NommerSdprod(self,sd,sdnom,restrict='non'):
551       """
552           Nomme la SD apres avoir verifie que le nommage est possible :
553           nom non utilise
554           Si le nom est deja utilise, leve une exception
555           Met le concept créé dans le concept global g_context
556       """
557       # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
558       # Le dictionnaire g_context ne représente pas le contexte
559       # effectif avant une étape.
560       # Il faut utiliser get_contexte_avant avec indication de l'étape
561       # traitée.
562       # Cette etape est indiquee par l'attribut _etape_context qui a ete
563       # positionné préalablement par un appel à set_etape_context
564
565       if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
566
567       if self._etape_context:
568          o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
569       else:
570          o=self.sds_dict.get(sdnom,None)
571
572       if isinstance(o,ASSD):
573          raise AsException("Nom de concept deja defini : %s" % sdnom)
574
575       # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
576       # Ajoute a la creation (appel de reg_sd).
577       self.sds_dict[sdnom]=sd
578       sd.nom=sdnom
579
580       # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
581       if restrict == 'non':
582          self.g_context[sdnom]=sd
583
584 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
585    def delete_concept_after_etape(self,etape,sd):
586       """
587           Met à jour les étapes du JDC qui sont après etape en fonction
588           de la disparition du concept sd
589       """
590       index = self.etapes.index(etape)+1
591       if index == len(self.etapes) :
592          return # etape est la dernière étape du jdc ...on ne fait rien !
593       for child in self.etapes[index:]:
594         child.delete_concept(sd)
595
596 #ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer
597