Salome HOME
This commit was generated by cvs2git to track changes on a CVS vendor
[tools/eficas.git] / Noyau / N_MCCOMPO.py
1 #@ MODIF N_MCCOMPO Noyau  DATE 29/05/2002   AUTEUR DURAND C.DURAND 
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     Ce module contient la classe MCCOMPO qui sert à factoriser les comportements 
23     des OBJECT composites
24 """
25
26 import types
27
28 import N_OBJECT
29
30 class MCCOMPO(N_OBJECT.OBJECT):
31    """
32       Classe support d'un OBJECT composite
33   
34    """
35
36    def build_mc(self):
37       """ 
38           Construit la liste des sous-entites du MCCOMPO
39           à partir du dictionnaire des arguments (valeur)
40       """
41       if CONTEXT.debug : print "MCCOMPO.build_mc ",self.nom
42       # Dans la phase de reconstruction args peut contenir des mots-clés
43       # qui ne sont pas dans le dictionnaire des entites de definition (self.definition.entites)
44       # de l'objet courant (self)
45       #  mais qui sont malgré tout des descendants de l'objet courant (petits-fils, ...)
46       args = self.valeur
47       if args == None : args ={}
48       mc_liste=[]
49
50       # On recopie le dictionnaire des arguments pour protéger l'original des delete (del args[k])
51       args = args.copy()
52
53       # Phase 1:
54       # On construit les sous entites presentes ou obligatoires
55       # 1- les entites présentes dans les arguments et dans la définition
56       # 2- les entités non présentes dans les arguments, présentes dans la définition avec un défaut
57       for k,v in self.definition.entites.items():
58         if args.has_key(k) or v.statut=='o' :
59           #
60           # Creation par appel de la methode __call__ de la definition de la sous entite k de self
61           # si une valeur existe dans args ou est obligatoire (generique si toutes les
62           # entites ont l attribut statut )
63           #
64           objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
65           mc_liste.append(objet)
66           # Si l'objet a une position globale on l'ajoute aux listes correspondantes
67           if hasattr(objet.definition,'position'):
68             if objet.definition.position == 'global' :
69               self.append_mc_global(objet)
70             elif objet.definition.position == 'global_jdc' :
71               self.append_mc_global_jdc(objet)
72         if args.has_key(k):
73            del args[k]
74
75       # Phase 2:
76       # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés.
77       # A ce stade, mc_liste ne contient que les fils de l'objet courant
78       # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont
79       #      à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés
80       dico_valeurs = self.cree_dict_valeurs(mc_liste)
81       for k,v in self.definition.entites.items():
82          if v.label != 'BLOC':continue
83          # condition and a or b  : Equivalent de l'expression :  condition ? a : b du langage C
84          globs= self.jdc and self.jdc.condition_context or {}
85          if v.verif_presence(dico_valeurs,globs):
86             # Si le bloc existe :
87             #        1- on le construit
88             #        2- on l'ajoute à mc_liste
89             #        3- on récupère les arguments restant
90             #        4- on reconstruit le dictionnaire équivalent à mc_liste
91             bloc = v(nom=k,val=args,parent=self)
92             mc_liste.append(bloc)
93             args=bloc.reste_val
94             dico_valeurs = self.cree_dict_valeurs(mc_liste)
95
96       # On conserve les arguments superflus dans l'attribut reste_val
97       self.reste_val=args
98       # On ordonne la liste ainsi créée suivant l'ordre du catalogue 
99       # (utile seulement pour IHM graphique)
100       mc_liste = self.ordonne_liste(mc_liste)
101       # on retourne la liste ainsi construite
102       return mc_liste
103
104    def ordonne_liste(self,mc_liste):
105       """
106          Ordonne la liste suivant l'ordre du catalogue.
107          Seulement pour IHM graphique
108       """
109       if self.jdc and self.jdc.cata_ordonne_dico != None :
110          liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(
111                        self.get_genealogie(),self.jdc.cata_ordonne_dico)
112          return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee)
113       else:
114          return mc_liste
115
116    def cree_dict_valeurs(self,liste=[]):
117       """ 
118         Cette méthode crée le contexte de l'objet courant sous la forme 
119         d'un dictionnaire.
120         L'opération consiste à transformer une liste d'OBJECT en un 
121         dictionnaire.
122         Ce dictionnaire servira de contexte pour évaluer les conditions des 
123         blocs fils.
124
125         Cette méthode réalise les opérations suivantes en plus de transformer 
126         la liste en dictionnaire :
127
128         - ajouter tous les mots-clés non présents avec la valeur None
129
130         - ajouter tous les mots-clés globaux (attribut position = 'global' 
131           et 'global_jdc')
132
133         ATTENTION : -- on ne remonte pas (semble en contradiction avec la 
134                       programmation de la méthode get_valeur du bloc) les 
135                       mots-clé fils d'un bloc au niveau du
136                       contexte car celà peut générer des erreurs.
137
138         L'argument liste est, en général, une mc_liste en cours de 
139         construction, contenant les mots-clés locaux et les blocs déjà créés.
140
141       """
142       dico={}
143       for v in liste:
144         k=v.nom
145         val = v.get_valeur()
146         # Si val est un dictionnaire, on inclut ses items dans le dictionnaire
147         # représentatif du contexte. Les blocs sont retournés par get_valeur
148         # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
149         # donc remontés au niveau du contexte.
150         if type(val)==types.DictionaryType:
151           for i,w in val.items():
152             dico[i]=w
153         else:
154           dico[k]=val
155       # on rajoute tous les autres mots-clés locaux possibles avec la valeur 
156       # par défaut ou None
157       # Pour les mots-clés facteurs, on ne tient pas compte du défaut 
158       # (toujours None)
159       for k,v in self.definition.entites.items():
160         if not dico.has_key(k):
161            if v.label == 'SIMP':
162               dico[k]=v.defaut
163               # S il est declare global il n est pas necessaire de l ajouter
164               # aux mots cles globaux de l'etape
165               # car la methode recherche_mc_globaux les rajoutera
166            elif v.label == 'FACT' and v.statut in ('c','d') :
167               dico[k]=v(val=None,nom=k,parent=self)
168               # On demande la suppression des pointeurs arrieres
169               # pour briser les eventuels cycles
170               dico[k].supprime()
171            elif v.label != 'BLOC':
172               dico[k]=None
173       # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
174       # valeur par défaut ou la valeur None
175       # on rajoute les mots-clés globaux ...
176       dico_mc = self.recherche_mc_globaux()
177       for nom,mc in dico_mc.items() :
178         if not dico.has_key(nom) : dico[nom]=mc.valeur
179       # Il nous reste à évaluer la présence des blocs en fonction du contexte qui a changé
180       for k,v in self.definition.entites.items():
181         if v.label != 'BLOC' : continue
182         # condition and a or b  : Equivalent de l'expression :  condition ? a : b du langage C
183         globs= self.jdc and self.jdc.condition_context or {}
184         if v.verif_presence(dico,globs):
185           # le bloc k doit etre présent : on crée temporairement l'objet MCBLOC correspondant
186           # on lui passe un parent égal à None pour qu'il ne soit pas enregistré
187           bloc = v(nom=k,val=None,parent=None)
188           dico_bloc = bloc.cree_dict_valeurs()
189           bloc.supprime()
190           # on va updater dico avec dico_bloc en veillant à ne pas écraser
191           # des valeurs déjà présentes
192           for cle in dico_bloc.keys():
193             if not dico.has_key(cle):
194               dico[cle]=dico_bloc[cle]
195       return dico
196
197    def recherche_mc_globaux(self):
198       """ 
199           Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
200           et des mots-clés globaux du jdc
201       """
202       etape = self.get_etape()
203       if etape :
204         dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
205         dict_mc_globaux_fac.update(etape.mc_globaux)
206         if self.jdc : dict_mc_globaux_fac.update(self.jdc.mc_globaux)
207         return dict_mc_globaux_fac
208       else :
209         return {}
210
211    def recherche_mc_globaux_facultatifs(self):
212       """ 
213           Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
214           directs de self de type 'global'
215       """
216       dico={}
217       etape = self.get_etape()
218       if not etape : return {}
219       for k,v in etape.definition.entites.items():
220          if v.label != 'SIMP' : continue
221          if v.position != 'global' : continue
222          if v.statut == 'o':continue
223          obj = v(val=None,nom=k,parent=etape)
224          dico[k]=obj
225       return dico
226
227    def supprime(self):
228       """ 
229          Méthode qui supprime toutes les références arrières afin que l'objet puisse
230          etre correctement détruit par le garbage collector
231       """
232       N_OBJECT.OBJECT.supprime(self)
233       for child in self.mc_liste :
234          child.supprime()
235
236    def __getitem__(self,key):
237       """
238          Cette méthode retourne la valeur d'un sous mot-clé (key)
239       """
240       return self.get_mocle(key)
241
242    def get_mocle(self,key):
243       """
244           Retourne la valeur du sous mot-clé key 
245           Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre 
246           dans un BLOC fils de self
247       """
248       # on cherche dans les mots cles presents, le mot cle de nom key
249       # s'il est là on retourne sa valeur (méthode get_val)
250       for child in self.mc_liste:
251         if child.nom == key : return child.get_val()
252       #  Si on n a pas trouve de mot cle present on retourne le defaut
253       #  eventuel pour les mots cles accessibles dans la definition
254       #  a ce niveau
255       try:
256         d=self.definition.entites[key]
257         if d.label == 'SIMP':
258           return d.defaut
259         elif d.label == 'FACT':
260           # il faut construire les objets necessaires pour
261           # evaluer les conditions des blocs eventuels (a faire)
262           if d.statut == 'o' :return None
263           if d.statut != 'c' and d.statut != 'd' :
264              return None
265           else :
266              return d(val=None,nom=key,parent=self)
267       except KeyError:
268         # le mot cle n est pas defini a ce niveau
269         pass
270       #  Si on a toujours rien trouve, on cherche dans les blocs presents
271       #  On suppose que tous les blocs possibles ont ete crees meme ceux
272       #  induits par un mot cle simple absent avec defaut (???)
273       for mc in self.mc_liste :
274         if not mc.isBLOC() : continue
275         try:
276           return mc.get_mocle(key)
277         except: 
278           # On n a rien trouve dans ce bloc, on passe au suivant
279           pass
280       #  On a rien trouve, le mot cle est absent.
281       #  On leve une exception
282       raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
283
284    def get_child(self,name,restreint = 'non'):
285       """ 
286           Retourne le fils de self de nom name ou None s'il n'existe pas
287           Si restreint vaut oui : ne regarde que dans la mc_liste
288           Si restreint vaut non : regarde aussi dans les entites possibles 
289           avec defaut    
290            (Ce dernier cas n'est utilisé que dans le catalogue)
291       """
292       for v in self.mc_liste:
293         if v.nom == name : return v
294       if restreint == 'non' :
295         for k,v in self.definition.entites.items():
296           if k == name:
297             if v.valeur != None : return v(None,k,None)
298       return None
299
300    def append_mc_global(self,mc):
301       """
302          Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
303       """
304       etape = self.get_etape()
305       if etape :
306         nom = mc.nom
307         etape.mc_globaux[nom]=mc
308
309    def append_mc_global_jdc(self,mc):
310       """ 
311           Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc 
312       """
313       nom = mc.nom
314       self.jdc.mc_globaux[nom]=mc
315
316
317