]> SALOME platform Git repositories - tools/eficas.git/blob - Noyau/N_MCCOMPO.py
Salome HOME
daa83e647cc00a32055094892fa41568912958a9
[tools/eficas.git] / Noyau / N_MCCOMPO.py
1 #@ MODIF N_MCCOMPO Noyau  DATE 03/09/2002   AUTEUR GNICOLAS G.NICOLAS 
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 from copy import copy
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            - ajouter tous les mots-clés globaux (attribut position = 'global' 
130              et 'global_jdc')
131
132         ATTENTION : on ne remonte pas (semble en contradiction avec la 
133         programmation de la méthode get_valeur du bloc) les 
134         mots-clé fils d'un bloc au niveau du
135         contexte car celà peut générer des erreurs.
136
137         L'argument liste est, en général, une mc_liste en cours de 
138         construction, contenant les mots-clés locaux et les blocs déjà créés.
139
140       """
141       dico={}
142       for v in liste:
143         k=v.nom
144         val = v.get_valeur()
145         # Si val est un dictionnaire, on inclut ses items dans le dictionnaire
146         # représentatif du contexte. Les blocs sont retournés par get_valeur
147         # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
148         # donc remontés au niveau du contexte.
149         if type(val)==types.DictionaryType:
150           for i,w in val.items():
151             dico[i]=w
152         else:
153           dico[k]=val
154       # on rajoute tous les autres mots-clés locaux possibles avec la valeur 
155       # par défaut ou None
156       # Pour les mots-clés facteurs, on ne tient pas compte du défaut 
157       # (toujours None)
158       for k,v in self.definition.entites.items():
159         if not dico.has_key(k):
160            if v.label == 'SIMP':
161               dico[k]=v.defaut
162               # S il est declare global il n est pas necessaire de l ajouter
163               # aux mots cles globaux de l'etape
164               # car la methode recherche_mc_globaux les rajoutera
165            elif v.label == 'FACT' and v.statut in ('c','d') :
166               dico[k]=v(val=None,nom=k,parent=self)
167               # On demande la suppression des pointeurs arrieres
168               # pour briser les eventuels cycles
169               dico[k].supprime()
170            elif v.label != 'BLOC':
171               dico[k]=None
172       # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
173       # valeur par défaut ou la valeur None
174       # on rajoute les mots-clés globaux ...
175       dico_mc = self.recherche_mc_globaux()
176       for nom,mc in dico_mc.items() :
177         if not dico.has_key(nom) : dico[nom]=mc.valeur
178       # Il nous reste à évaluer la présence des blocs en fonction du contexte qui a changé
179       for k,v in self.definition.entites.items():
180         if v.label != 'BLOC' : continue
181         # condition and a or b  : Equivalent de l'expression :  condition ? a : b du langage C
182         globs= self.jdc and self.jdc.condition_context or {}
183         if v.verif_presence(dico,globs):
184           # le bloc k doit etre présent : on crée temporairement l'objet MCBLOC correspondant
185           # on lui passe un parent égal à None pour qu'il ne soit pas enregistré
186           bloc = v(nom=k,val=None,parent=None)
187           dico_bloc = bloc.cree_dict_valeurs()
188           bloc.supprime()
189           # on va updater dico avec dico_bloc en veillant à ne pas écraser
190           # des valeurs déjà présentes
191           for cle in dico_bloc.keys():
192             if not dico.has_key(cle):
193               dico[cle]=dico_bloc[cle]
194       return dico
195
196    def recherche_mc_globaux(self):
197       """ 
198           Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
199           et des mots-clés globaux du jdc
200       """
201       etape = self.get_etape()
202       if etape :
203         dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
204         dict_mc_globaux_fac.update(etape.mc_globaux)
205         if self.jdc : dict_mc_globaux_fac.update(self.jdc.mc_globaux)
206         return dict_mc_globaux_fac
207       else :
208         return {}
209
210    def recherche_mc_globaux_facultatifs(self):
211       """ 
212           Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
213           directs de self de type 'global'
214       """
215       dico={}
216       etape = self.get_etape()
217       if not etape : return {}
218       for k,v in etape.definition.entites.items():
219          if v.label != 'SIMP' : continue
220          if v.position != 'global' : continue
221          if v.statut == 'o':continue
222          obj = v(val=None,nom=k,parent=etape)
223          dico[k]=obj
224       return dico
225
226    def supprime(self):
227       """ 
228          Méthode qui supprime toutes les références arrières afin que l'objet puisse
229          etre correctement détruit par le garbage collector
230       """
231       N_OBJECT.OBJECT.supprime(self)
232       for child in self.mc_liste :
233          child.supprime()
234
235    def __getitem__(self,key):
236       """
237          Cette méthode retourne la valeur d'un sous mot-clé (key)
238       """
239       return self.get_mocle(key)
240
241    def get_mocle(self,key):
242       """
243           Retourne la valeur du sous mot-clé key 
244           Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre 
245           dans un BLOC fils de self
246       """
247       # on cherche dans les mots cles presents, le mot cle de nom key
248       # s'il est là on retourne sa valeur (méthode get_val)
249       for child in self.mc_liste:
250         if child.nom == key : return child.get_val()
251       #  Si on n a pas trouve de mot cle present on retourne le defaut
252       #  eventuel pour les mots cles accessibles dans la definition
253       #  a ce niveau
254       try:
255         d=self.definition.entites[key]
256         if d.label == 'SIMP':
257           return d.defaut
258         elif d.label == 'FACT':
259           # il faut construire les objets necessaires pour
260           # evaluer les conditions des blocs eventuels (a faire)
261           if d.statut == 'o' :return None
262           if d.statut != 'c' and d.statut != 'd' :
263              return None
264           else :
265              return d(val=None,nom=key,parent=self)
266       except KeyError:
267         # le mot cle n est pas defini a ce niveau
268         pass
269       #  Si on a toujours rien trouve, on cherche dans les blocs presents
270       #  On suppose que tous les blocs possibles ont ete crees meme ceux
271       #  induits par un mot cle simple absent avec defaut (???)
272       for mc in self.mc_liste :
273         if not mc.isBLOC() : continue
274         try:
275           return mc.get_mocle(key)
276         except: 
277           # On n a rien trouve dans ce bloc, on passe au suivant
278           pass
279       #  On a rien trouve, le mot cle est absent.
280       #  On leve une exception
281       raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
282
283    def get_child(self,name,restreint = 'non'):
284       """ 
285           Retourne le fils de self de nom name ou None s'il n'existe pas
286           Si restreint vaut oui : ne regarde que dans la mc_liste
287           Si restreint vaut non : regarde aussi dans les entites possibles 
288           avec defaut. (Ce dernier cas n'est utilisé que dans le catalogue)
289       """
290       for v in self.mc_liste:
291         if v.nom == name : return v
292       if restreint == 'non' :
293         for k,v in self.definition.entites.items():
294           if k == name:
295             if v.valeur != None : return v(None,k,None)
296       return None
297
298    def append_mc_global(self,mc):
299       """
300          Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
301       """
302       etape = self.get_etape()
303       if etape :
304         nom = mc.nom
305         etape.mc_globaux[nom]=mc
306
307    def append_mc_global_jdc(self,mc):
308       """ 
309           Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc 
310       """
311       nom = mc.nom
312       self.jdc.mc_globaux[nom]=mc
313
314    def copy(self):
315     """ Retourne une copie de self """
316     objet = self.makeobjet()
317     # FR : attention !!! avec makeobjet, objet a le meme parent que self
318     # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
319     # FR : peut-on passer par là autrement que dans le cas d'une copie ???
320     # FR --> je suppose que non
321     # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
322     # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
323     objet.valeur = copy(self.valeur)
324     objet.val = copy(self.val)
325     objet.mc_liste=[]
326     for obj in self.mc_liste:
327       new_obj = obj.copy()
328       new_obj.reparent(objet)
329       objet.mc_liste.append(new_obj)
330     return objet
331
332    def reparent(self,parent):
333      """
334          Cette methode sert a reinitialiser la parente de l'objet
335      """
336      self.parent=parent
337      self.jdc=parent.get_jdc_root()
338      self.etape=parent.etape
339      for mocle in self.mc_liste:
340         mocle.reparent(self)
341
342    def get_sd_utilisees(self):
343     """ 
344         Retourne la liste des concepts qui sont utilisés à l'intérieur de self
345         ( comme valorisation d'un MCS) 
346     """
347     l=[]
348     for child in self.mc_liste:
349       l.extend(child.get_sd_utilisees())
350     return l