1 #@ MODIF N_MCCOMPO Noyau DATE 18/12/2007 AUTEUR COURTOIS M.COURTOIS
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
32 class MCCOMPO(N_OBJECT.OBJECT):
34 Classe support d'un OBJECT composite
40 Construit la liste des sous-entites du MCCOMPO
41 à partir du dictionnaire des arguments (valeur)
43 if CONTEXT.debug : print "MCCOMPO.build_mc ",self.nom
44 # Dans la phase de reconstruction args peut contenir des mots-clés
45 # qui ne sont pas dans le dictionnaire des entites de definition (self.definition.entites)
46 # de l'objet courant (self)
47 # mais qui sont malgré tout des descendants de l'objet courant (petits-fils, ...)
49 if args == None : args ={}
52 # On recopie le dictionnaire des arguments pour protéger l'original des delete (del args[k])
56 # On construit les sous entites presentes ou obligatoires
57 # 1- les entites présentes dans les arguments et dans la définition
58 # 2- les entités non présentes dans les arguments, présentes dans la définition avec un défaut
59 # Phase 1.1 : on traite d'abord les SIMP pour enregistrer les mots cles globaux
60 for k,v in self.definition.entites.items():
61 if v.label != 'SIMP':continue
62 if args.has_key(k) or v.statut=='o' :
64 # Creation par appel de la methode __call__ de la definition de la sous entite k de self
65 # si une valeur existe dans args ou est obligatoire (generique si toutes les
66 # entites ont l attribut statut )
68 objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
69 mc_liste.append(objet)
70 # Si l'objet a une position globale on l'ajoute aux listes correspondantes
71 if hasattr(objet.definition,'position'):
72 if objet.definition.position == 'global' :
73 self.append_mc_global(objet)
74 elif objet.definition.position == 'global_jdc' :
75 self.append_mc_global_jdc(objet)
79 # Phase 1.2 : on traite les autres entites que SIMP
80 for k,v in self.definition.entites.items():
81 if v.label == 'SIMP':continue
82 if args.has_key(k) or v.statut=='o' :
84 # Creation par appel de la methode __call__ de la definition de la sous entite k de self
85 # si une valeur existe dans args ou est obligatoire (generique si toutes les
86 # entites ont l attribut statut )
88 objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
89 mc_liste.append(objet)
94 # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés.
95 # A ce stade, mc_liste ne contient que les fils de l'objet courant
96 # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont
97 # à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés
98 dico_valeurs = self.cree_dict_condition(mc_liste,condition=1)
99 for k,v in self.definition.entites.items():
100 if v.label != 'BLOC':continue
101 # condition and a or b : Equivalent de l'expression : condition ? a : b du langage C
102 globs= self.jdc and self.jdc.condition_context or {}
103 if v.verif_presence(dico_valeurs,globs):
104 # Si le bloc existe :
106 # 2- on l'ajoute à mc_liste
107 # 3- on récupère les arguments restant
108 # 4- on reconstruit le dictionnaire équivalent à mc_liste
109 bloc = v(nom=k,val=args,parent=self)
110 mc_liste.append(bloc)
112 # On ne recalcule pas le contexte car on ne tient pas compte des blocs
113 # pour évaluer les conditions de présence des blocs
114 #dico_valeurs = self.cree_dict_valeurs(mc_liste)
116 # On conserve les arguments superflus dans l'attribut reste_val
118 # On ordonne la liste ainsi créée suivant l'ordre du catalogue
119 # (utile seulement pour IHM graphique)
120 mc_liste = self.ordonne_liste(mc_liste)
121 # on retourne la liste ainsi construite
124 def ordonne_liste(self,mc_liste):
126 Ordonne la liste suivant l'ordre du catalogue.
127 Seulement pour IHM graphique
129 if self.jdc and self.jdc.cata_ordonne_dico != None :
130 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(
131 self.get_genealogie(),self.jdc.cata_ordonne_dico)
132 return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee)
136 def cree_dict_valeurs(self,liste=[],condition=0):
138 Cette méthode crée un contexte (sous la forme d'un dictionnaire)
139 à partir des valeurs des mots clés contenus dans l'argument liste.
140 L'opération consiste à parcourir la liste (d'OBJECT) et à la
141 transformer en un dictionnaire dont les clés sont les noms des
142 mots clés et les valeurs dépendent du type d'OBJECT.
143 Ce dictionnaire servira de liste d'arguments d'appel pour les
144 fonctions sd_prod de commandes et ops de macros ou de contexte
145 d'évaluation des conditions de présence de BLOC.
147 Si l'argument condition de la méthode vaut 1, on ne
148 remonte pas les valeurs des mots clés contenus dans des blocs
149 pour eviter les bouclages.
151 Cette méthode réalise les opérations suivantes en plus de transformer
152 la liste en dictionnaire :
154 - ajouter tous les mots-clés non présents avec la valeur None
155 - ajouter tous les mots-clés globaux (attribut position = 'global'
158 L'argument liste est, en général, une mc_liste en cours de
159 construction, contenant les mots-clés locaux et les blocs déjà créés.
165 # Si v est un BLOC, on inclut ses items dans le dictionnaire
166 # représentatif du contexte. Les blocs sont retournés par get_valeur
167 # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
168 # donc remontés au niveau du contexte.
169 if not condition:dico.update(v.get_valeur())
171 dico[v.nom]=v.get_valeur()
173 # On rajoute tous les autres mots-clés locaux possibles avec la valeur
175 # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d')
177 # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement
179 for k,v in self.definition.entites.items():
180 if not dico.has_key(k):
181 if v.label == 'SIMP':
184 elif v.label == 'FACT' :
185 if v.statut in ('c','d') :
186 # Mot clé facteur avec défaut ou caché provisoire
187 dico[k]=v(val=None,nom=k,parent=self)
188 # On demande la suppression des pointeurs arrieres
189 # pour briser les eventuels cycles
193 # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
194 # valeur par défaut ou la valeur None
196 # On rajoute les mots-clés globaux sans écraser les clés existantes
197 dico_mc = self.recherche_mc_globaux()
203 def cree_dict_condition(self,liste=[],condition=0):
205 Methode pour construire un contexte qui servira dans l'évaluation
206 des conditions de présence de blocs. Si une commande a un concept
207 produit réutilisé, on ajoute la clé 'reuse'
209 dico=self.cree_dict_valeurs(liste,condition=1)
210 # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination
211 # uniquement des commandes. Ne devrait pas etre dans cette classe mais dans une classe dérivée
212 if not dico.has_key('reuse') and hasattr(self,'reuse'):
213 dico['reuse']=self.reuse
216 def recherche_mc_globaux(self):
218 Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
219 et des mots-clés globaux du jdc
221 etape = self.get_etape()
223 dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
224 for k,v in etape.mc_globaux.items():
225 dict_mc_globaux_fac[k]=v.get_valeur()
227 for k,v in self.jdc.mc_globaux.items():
228 dict_mc_globaux_fac[k]=v.get_valeur()
229 return dict_mc_globaux_fac
233 def recherche_mc_globaux_facultatifs(self):
235 Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
236 directs de self de type 'global'
239 etape = self.get_etape()
240 if not etape : return {}
241 for k,v in etape.definition.entites.items():
242 if v.label != 'SIMP' : continue
243 if v.position != 'global' : continue
244 if v.statut == 'o':continue
245 obj = v(val=None,nom=k,parent=etape)
246 dico[k]=obj.get_valeur()
251 Méthode qui supprime toutes les références arrières afin que l'objet puisse
252 etre correctement détruit par le garbage collector
254 N_OBJECT.OBJECT.supprime(self)
255 for child in self.mc_liste :
258 def __getitem__(self,key):
260 Cette méthode retourne la valeur d'un sous mot-clé (key)
262 return self.get_mocle(key)
264 def get_mocle(self,key):
266 Retourne la valeur du sous mot-clé key
267 Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre
268 dans un BLOC fils de self
270 # on cherche dans les mots cles presents, le mot cle de nom key
271 # s'il est là on retourne sa valeur (méthode get_val)
272 for child in self.mc_liste:
273 if child.nom == key : return child.get_val()
274 # Si on n a pas trouve de mot cle present on retourne le defaut
275 # eventuel pour les mots cles accessibles dans la definition
278 d=self.definition.entites[key]
279 if d.label == 'SIMP':
281 elif d.label == 'FACT':
282 # il faut construire les objets necessaires pour
283 # evaluer les conditions des blocs eventuels (a faire)
284 if d.statut == 'o' :return None
285 if d.statut != 'c' and d.statut != 'd' :
288 return d(val=None,nom=key,parent=self)
290 # le mot cle n est pas defini a ce niveau
292 # Si on a toujours rien trouve, on cherche dans les blocs presents
293 # On suppose que tous les blocs possibles ont ete crees meme ceux
294 # induits par un mot cle simple absent avec defaut (???)
295 for mc in self.mc_liste :
296 if not mc.isBLOC() : continue
298 return mc.get_mocle(key)
300 # On n a rien trouve dans ce bloc, on passe au suivant
302 # On a rien trouve, le mot cle est absent.
303 # On leve une exception
304 raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
306 def get_child(self,name,restreint = 'non'):
308 Retourne le fils de self de nom name ou None s'il n'existe pas
309 Si restreint vaut oui : ne regarde que dans la mc_liste
310 Si restreint vaut non : regarde aussi dans les entites possibles
311 avec defaut (Ce dernier cas n'est utilisé que dans le catalogue)
313 for v in self.mc_liste:
314 if v.nom == name : return v
315 if restreint == 'non' :
317 entite=self.definition.entites[name]
318 if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ( 'c', 'd')):
319 return entite(None,name,None)
325 def append_mc_global(self,mc):
327 Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
329 etape = self.get_etape()
332 etape.mc_globaux[nom]=mc
334 def append_mc_global_jdc(self,mc):
336 Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc
339 self.jdc.mc_globaux[nom]=mc
342 """ Retourne une copie de self """
343 objet = self.makeobjet()
344 # FR : attention !!! avec makeobjet, objet a le meme parent que self
345 # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
346 # FR : peut-on passer par là autrement que dans le cas d'une copie ???
347 # FR --> je suppose que non
348 # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
349 # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
350 objet.valeur = copy(self.valeur)
351 objet.val = copy(self.val)
353 for obj in self.mc_liste:
355 new_obj.reparent(objet)
356 objet.mc_liste.append(new_obj)
359 def reparent(self,parent):
361 Cette methode sert a reinitialiser la parente de l'objet
364 self.jdc=parent.get_jdc_root()
365 self.etape=parent.etape
366 for mocle in self.mc_liste:
369 def get_sd_utilisees(self):
371 Retourne la liste des concepts qui sont utilisés à l'intérieur de self
372 ( comme valorisation d'un MCS)
375 for child in self.mc_liste:
376 l.extend(child.get_sd_utilisees())
379 def get_sd_mcs_utilisees(self):
381 Retourne la ou les SD utilisée par self sous forme d'un dictionnaire :
382 - Si aucune sd n'est utilisée, le dictionnaire est vide.
383 - Sinon, les clés du dictionnaire sont les mots-clés derrière lesquels on
384 trouve des sd ; la valeur est la liste des sd attenante.
387 { 'VALE_F': [ <Cata.cata.para_sensi instance at 0x9419854>,
388 <Cata.cata.para_sensi instance at 0x941a204> ],
389 'MODELE': [<Cata.cata.modele instance at 0x941550c>] }
392 for child in self.mc_liste:
393 daux = child.get_sd_mcs_utilisees()
394 for cle in daux.keys():
395 dico[cle] = dico.get(cle, [])
396 dico[cle].extend(daux[cle])
399 def get_mcs_with_co(self,co):
401 Cette methode retourne l'objet MCSIMP fils de self
402 qui a le concept co comme valeur.
403 En principe, elle ne doit etre utilisee que pour les concepts
404 instances de la classe CO
407 for child in self.mc_liste:
408 l.extend(child.get_mcs_with_co(co))
411 def get_all_co(self):
413 Cette methode retourne tous les concepts instances de CO
416 for child in self.mc_liste:
417 l.extend(child.get_all_co())