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