1 #@ MODIF N_MCCOMPO Noyau DATE 20/10/2004 AUTEUR DURAND C.DURAND
2 # -*- coding: iso-8859-1 -*-
3 # CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
9 # (AT YOUR OPTION) ANY LATER VERSION.
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
18 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
21 # ======================================================================
25 Ce module contient la classe MCCOMPO qui sert à factoriser les comportements
33 class MCCOMPO(N_OBJECT.OBJECT):
35 Classe support d'un OBJECT composite
41 Construit la liste des sous-entites du MCCOMPO
42 à partir du dictionnaire des arguments (valeur)
44 if CONTEXT.debug : print "MCCOMPO.build_mc ",self.nom
45 # Dans la phase de reconstruction args peut contenir des mots-clés
46 # qui ne sont pas dans le dictionnaire des entites de definition (self.definition.entites)
47 # de l'objet courant (self)
48 # mais qui sont malgré tout des descendants de l'objet courant (petits-fils, ...)
50 if args == None : args ={}
53 # On recopie le dictionnaire des arguments pour protéger l'original des delete (del args[k])
57 # On construit les sous entites presentes ou obligatoires
58 # 1- les entites présentes dans les arguments et dans la définition
59 # 2- les entités non présentes dans les arguments, présentes dans la définition avec un défaut
60 for k,v in self.definition.entites.items():
61 if args.has_key(k) or v.statut=='o' :
63 # Creation par appel de la methode __call__ de la definition de la sous entite k de self
64 # si une valeur existe dans args ou est obligatoire (generique si toutes les
65 # entites ont l attribut statut )
67 objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
68 mc_liste.append(objet)
69 # Si l'objet a une position globale on l'ajoute aux listes correspondantes
70 if hasattr(objet.definition,'position'):
71 if objet.definition.position == 'global' :
72 self.append_mc_global(objet)
73 elif objet.definition.position == 'global_jdc' :
74 self.append_mc_global_jdc(objet)
79 # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés.
80 # A ce stade, mc_liste ne contient que les fils de l'objet courant
81 # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont
82 # à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés
83 dico_valeurs = self.cree_dict_condition(mc_liste,condition=1)
84 for k,v in self.definition.entites.items():
85 if v.label != 'BLOC':continue
86 # condition and a or b : Equivalent de l'expression : condition ? a : b du langage C
87 globs= self.jdc and self.jdc.condition_context or {}
88 if v.verif_presence(dico_valeurs,globs):
91 # 2- on l'ajoute à mc_liste
92 # 3- on récupère les arguments restant
93 # 4- on reconstruit le dictionnaire équivalent à mc_liste
94 bloc = v(nom=k,val=args,parent=self)
97 # On ne recalcule pas le contexte car on ne tient pas compte des blocs
98 # pour évaluer les conditions de présence des blocs
99 #dico_valeurs = self.cree_dict_valeurs(mc_liste)
101 # On conserve les arguments superflus dans l'attribut reste_val
103 # On ordonne la liste ainsi créée suivant l'ordre du catalogue
104 # (utile seulement pour IHM graphique)
105 mc_liste = self.ordonne_liste(mc_liste)
106 # on retourne la liste ainsi construite
109 def ordonne_liste(self,mc_liste):
111 Ordonne la liste suivant l'ordre du catalogue.
112 Seulement pour IHM graphique
114 if self.jdc and self.jdc.cata_ordonne_dico != None :
115 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(
116 self.get_genealogie(),self.jdc.cata_ordonne_dico)
117 return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee)
121 def cree_dict_valeurs(self,liste=[],condition=0):
123 Cette méthode crée un contexte (sous la forme d'un dictionnaire)
124 à partir des valeurs des mots clés contenus dans l'argument liste.
125 L'opération consiste à parcourir la liste (d'OBJECT) et à la
126 transformer en un dictionnaire dont les clés sont les noms des
127 mots clés et les valeurs dépendent du type d'OBJECT.
128 Ce dictionnaire servira de liste d'arguments d'appel pour les
129 fonctions sd_prod de commandes et ops de macros ou de contexte
130 d'évaluation des conditions de présence de BLOC.
132 Si l'argument condition de la méthode vaut 1, on ne
133 remonte pas les valeurs des mots clés contenus dans des blocs
134 pour eviter les bouclages.
136 Cette méthode réalise les opérations suivantes en plus de transformer
137 la liste en dictionnaire :
139 - ajouter tous les mots-clés non présents avec la valeur None
140 - ajouter tous les mots-clés globaux (attribut position = 'global'
143 L'argument liste est, en général, une mc_liste en cours de
144 construction, contenant les mots-clés locaux et les blocs déjà créés.
150 # Si v est un BLOC, on inclut ses items dans le dictionnaire
151 # représentatif du contexte. Les blocs sont retournés par get_valeur
152 # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
153 # donc remontés au niveau du contexte.
154 if not condition:dico.update(v.get_valeur())
156 dico[v.nom]=v.get_valeur()
158 # On rajoute tous les autres mots-clés locaux possibles avec la valeur
160 # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d')
162 # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement
164 for k,v in self.definition.entites.items():
165 if not dico.has_key(k):
166 if v.label == 'SIMP':
169 elif v.label == 'FACT' :
170 if v.statut in ('c','d') :
171 # Mot clé facteur avec défaut ou caché provisoire
172 dico[k]=v(val=None,nom=k,parent=self)
173 # On demande la suppression des pointeurs arrieres
174 # pour briser les eventuels cycles
178 # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
179 # valeur par défaut ou la valeur None
181 # On rajoute les mots-clés globaux sans écraser les clés existantes
182 dico_mc = self.recherche_mc_globaux()
188 def cree_dict_condition(self,liste=[],condition=0):
190 Methode pour construire un contexte qui servira dans l'évaluation
191 des conditions de présence de blocs. Si une commande a un concept
192 produit réutilisé, on ajoute la clé 'reuse'
194 dico=self.cree_dict_valeurs(liste,condition=1)
195 # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination
196 # uniquement des commandes. Ne devrait pas etre dans cette classe mais dans une classe dérivée
197 if not dico.has_key('reuse') and hasattr(self,'reuse'):
198 dico['reuse']=self.reuse
201 def recherche_mc_globaux(self):
203 Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
204 et des mots-clés globaux du jdc
206 etape = self.get_etape()
208 dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
209 for k,v in etape.mc_globaux.items():
210 dict_mc_globaux_fac[k]=v.get_valeur()
212 for k,v in self.jdc.mc_globaux.items():
213 dict_mc_globaux_fac[k]=v.get_valeur()
214 return dict_mc_globaux_fac
218 def recherche_mc_globaux_facultatifs(self):
220 Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
221 directs de self de type 'global'
224 etape = self.get_etape()
225 if not etape : return {}
226 for k,v in etape.definition.entites.items():
227 if v.label != 'SIMP' : continue
228 if v.position != 'global' : continue
229 if v.statut == 'o':continue
230 obj = v(val=None,nom=k,parent=etape)
231 dico[k]=obj.get_valeur()
236 Méthode qui supprime toutes les références arrières afin que l'objet puisse
237 etre correctement détruit par le garbage collector
239 N_OBJECT.OBJECT.supprime(self)
240 for child in self.mc_liste :
243 def __getitem__(self,key):
245 Cette méthode retourne la valeur d'un sous mot-clé (key)
247 return self.get_mocle(key)
249 def get_mocle(self,key):
251 Retourne la valeur du sous mot-clé key
252 Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre
253 dans un BLOC fils de self
255 # on cherche dans les mots cles presents, le mot cle de nom key
256 # s'il est là on retourne sa valeur (méthode get_val)
257 for child in self.mc_liste:
258 if child.nom == key : return child.get_val()
259 # Si on n a pas trouve de mot cle present on retourne le defaut
260 # eventuel pour les mots cles accessibles dans la definition
263 d=self.definition.entites[key]
264 if d.label == 'SIMP':
266 elif d.label == 'FACT':
267 # il faut construire les objets necessaires pour
268 # evaluer les conditions des blocs eventuels (a faire)
269 if d.statut == 'o' :return None
270 if d.statut != 'c' and d.statut != 'd' :
273 return d(val=None,nom=key,parent=self)
275 # le mot cle n est pas defini a ce niveau
277 # Si on a toujours rien trouve, on cherche dans les blocs presents
278 # On suppose que tous les blocs possibles ont ete crees meme ceux
279 # induits par un mot cle simple absent avec defaut (???)
280 for mc in self.mc_liste :
281 if not mc.isBLOC() : continue
283 return mc.get_mocle(key)
285 # On n a rien trouve dans ce bloc, on passe au suivant
287 # On a rien trouve, le mot cle est absent.
288 # On leve une exception
289 raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
291 def get_child(self,name,restreint = 'non'):
293 Retourne le fils de self de nom name ou None s'il n'existe pas
294 Si restreint vaut oui : ne regarde que dans la mc_liste
295 Si restreint vaut non : regarde aussi dans les entites possibles
297 (Ce dernier cas n'est utilisé que dans le catalogue)
299 for v in self.mc_liste:
300 if v.nom == name : return v
301 if restreint == 'non' :
303 entite=self.definition.entites[name]
304 if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ( 'c', 'd')):
305 return entite(None,name,None)
311 def append_mc_global(self,mc):
313 Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
315 etape = self.get_etape()
318 etape.mc_globaux[nom]=mc
320 def append_mc_global_jdc(self,mc):
322 Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc
325 self.jdc.mc_globaux[nom]=mc
328 """ Retourne une copie de self """
329 objet = self.makeobjet()
330 # FR : attention !!! avec makeobjet, objet a le meme parent que self
331 # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
332 # FR : peut-on passer par là autrement que dans le cas d'une copie ???
333 # FR --> je suppose que non
334 # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
335 # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
336 objet.valeur = copy(self.valeur)
337 objet.val = copy(self.val)
339 for obj in self.mc_liste:
341 new_obj.reparent(objet)
342 objet.mc_liste.append(new_obj)
345 def reparent(self,parent):
347 Cette methode sert a reinitialiser la parente de l'objet
350 self.jdc=parent.get_jdc_root()
351 self.etape=parent.etape
352 for mocle in self.mc_liste:
355 def get_sd_utilisees(self):
357 Retourne la liste des concepts qui sont utilisés à l'intérieur de self
358 ( comme valorisation d'un MCS)
361 for child in self.mc_liste:
362 l.extend(child.get_sd_utilisees())
365 def get_sd_mcs_utilisees(self):
367 Retourne la ou les SD utilisée par self sous forme d'un dictionnaire :
368 . Si aucune sd n'est utilisée, le dictionnaire est vide.
369 . Sinon, les clés du dictionnaire sont les mots-clés derrière lesquels on
370 trouve des sd ; la valeur est la liste des sd attenante.
371 Exemple : { 'VALE_F': [ <Cata.cata.para_sensi instance at 0x9419854>,
372 <Cata.cata.para_sensi instance at 0x941a204> ],
373 'MODELE': [<Cata.cata.modele instance at 0x941550c>] }
376 for child in self.mc_liste:
377 daux = child.get_sd_mcs_utilisees()
378 for cle in daux.keys():
379 dico[cle] = daux[cle]