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.
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.
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.
20 # ======================================================================
22 Ce module contient la classe MCCOMPO qui sert à factoriser les comportements
30 class MCCOMPO(N_OBJECT.OBJECT):
32 Classe support d'un OBJECT composite
38 Construit la liste des sous-entites du MCCOMPO
39 à partir du dictionnaire des arguments (valeur)
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, ...)
47 if args == None : args ={}
50 # On recopie le dictionnaire des arguments pour protéger l'original des delete (del args[k])
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' :
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 )
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)
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):
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)
94 dico_valeurs = self.cree_dict_valeurs(mc_liste)
96 # On conserve les arguments superflus dans l'attribut reste_val
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
104 def ordonne_liste(self,mc_liste):
106 Ordonne la liste suivant l'ordre du catalogue.
107 Seulement pour IHM graphique
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)
116 def cree_dict_valeurs(self,liste=[]):
118 Cette méthode crée le contexte de l'objet courant sous la forme
120 L'opération consiste à transformer une liste d'OBJECT en un
122 Ce dictionnaire servira de contexte pour évaluer les conditions des
125 Cette méthode réalise les opérations suivantes en plus de transformer
126 la liste en dictionnaire :
128 - ajouter tous les mots-clés non présents avec la valeur None
130 - ajouter tous les mots-clés globaux (attribut position = 'global'
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.
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.
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():
155 # on rajoute tous les autres mots-clés locaux possibles avec la valeur
157 # Pour les mots-clés facteurs, on ne tient pas compte du défaut
159 for k,v in self.definition.entites.items():
160 if not dico.has_key(k):
161 if v.label == 'SIMP':
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
171 elif v.label != 'BLOC':
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()
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]
197 def recherche_mc_globaux(self):
199 Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
200 et des mots-clés globaux du jdc
202 etape = self.get_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
211 def recherche_mc_globaux_facultatifs(self):
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'
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)
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
232 N_OBJECT.OBJECT.supprime(self)
233 for child in self.mc_liste :
236 def __getitem__(self,key):
238 Cette méthode retourne la valeur d'un sous mot-clé (key)
240 return self.get_mocle(key)
242 def get_mocle(self,key):
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
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
256 d=self.definition.entites[key]
257 if d.label == 'SIMP':
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' :
266 return d(val=None,nom=key,parent=self)
268 # le mot cle n est pas defini a ce niveau
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
276 return mc.get_mocle(key)
278 # On n a rien trouve dans ce bloc, on passe au suivant
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)
284 def get_child(self,name,restreint = 'non'):
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
290 (Ce dernier cas n'est utilisé que dans le catalogue)
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():
297 if v.valeur != None : return v(None,k,None)
300 def append_mc_global(self,mc):
302 Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
304 etape = self.get_etape()
307 etape.mc_globaux[nom]=mc
309 def append_mc_global_jdc(self,mc):
311 Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc
314 self.jdc.mc_globaux[nom]=mc
317 """ Retourne une copie de self """
318 objet = self.makeobjet()
319 # FR : attention !!! avec makeobjet, objet a le meme parent que self
320 # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
321 # FR : peut-on passer par là autrement que dans le cas d'une copie ???
322 # FR --> je suppose que non
323 # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
324 # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
325 objet.valeur = copy(self.valeur)
326 objet.val = copy(self.val)
328 for obj in self.mc_liste:
330 new_obj.reparent(objet)
331 objet.mc_liste.append(new_obj)
334 def reparent(self,parent):
336 Cette methode sert a reinitialiser la parente de l'objet
339 self.jdc=parent.get_jdc_root()
340 self.etape=parent.etape
341 for mocle in self.mc_liste:
344 def get_sd_utilisees(self):
346 Retourne la liste des concepts qui sont utilisés à l'intérieur de self
347 ( comme valorisation d'un MCS)
350 for child in self.mc_liste:
351 l.extend(child.get_sd_utilisees())