1 #@ MODIF N_MCCOMPO Noyau DATE 21/03/2005 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 # Phase 1.1 : on traite d'abord les SIMP pour enregistrer les mots cles globaux
61 for k,v in self.definition.entites.items():
62 if v.label != 'SIMP':continue
63 if args.has_key(k) or v.statut=='o' :
65 # Creation par appel de la methode __call__ de la definition de la sous entite k de self
66 # si une valeur existe dans args ou est obligatoire (generique si toutes les
67 # entites ont l attribut statut )
69 objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
70 mc_liste.append(objet)
71 # Si l'objet a une position globale on l'ajoute aux listes correspondantes
72 if hasattr(objet.definition,'position'):
73 if objet.definition.position == 'global' :
74 self.append_mc_global(objet)
75 elif objet.definition.position == 'global_jdc' :
76 self.append_mc_global_jdc(objet)
80 # Phase 1.2 : on traite les autres entites que SIMP
81 for k,v in self.definition.entites.items():
82 if v.label == 'SIMP':continue
83 if args.has_key(k) or v.statut=='o' :
85 # Creation par appel de la methode __call__ de la definition de la sous entite k de self
86 # si une valeur existe dans args ou est obligatoire (generique si toutes les
87 # entites ont l attribut statut )
89 objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
90 mc_liste.append(objet)
95 # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés.
96 # A ce stade, mc_liste ne contient que les fils de l'objet courant
97 # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont
98 # à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés
99 dico_valeurs = self.cree_dict_condition(mc_liste,condition=1)
100 for k,v in self.definition.entites.items():
101 if v.label != 'BLOC':continue
102 # condition and a or b : Equivalent de l'expression : condition ? a : b du langage C
103 globs= self.jdc and self.jdc.condition_context or {}
104 if v.verif_presence(dico_valeurs,globs):
105 # Si le bloc existe :
107 # 2- on l'ajoute à mc_liste
108 # 3- on récupère les arguments restant
109 # 4- on reconstruit le dictionnaire équivalent à mc_liste
110 bloc = v(nom=k,val=args,parent=self)
111 mc_liste.append(bloc)
113 # On ne recalcule pas le contexte car on ne tient pas compte des blocs
114 # pour évaluer les conditions de présence des blocs
115 #dico_valeurs = self.cree_dict_valeurs(mc_liste)
117 # On conserve les arguments superflus dans l'attribut reste_val
119 # On ordonne la liste ainsi créée suivant l'ordre du catalogue
120 # (utile seulement pour IHM graphique)
121 mc_liste = self.ordonne_liste(mc_liste)
122 # on retourne la liste ainsi construite
125 def ordonne_liste(self,mc_liste):
127 Ordonne la liste suivant l'ordre du catalogue.
128 Seulement pour IHM graphique
130 if self.jdc and self.jdc.cata_ordonne_dico != None :
131 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(
132 self.get_genealogie(),self.jdc.cata_ordonne_dico)
133 return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee)
137 def cree_dict_valeurs(self,liste=[],condition=0):
139 Cette méthode crée un contexte (sous la forme d'un dictionnaire)
140 à partir des valeurs des mots clés contenus dans l'argument liste.
141 L'opération consiste à parcourir la liste (d'OBJECT) et à la
142 transformer en un dictionnaire dont les clés sont les noms des
143 mots clés et les valeurs dépendent du type d'OBJECT.
144 Ce dictionnaire servira de liste d'arguments d'appel pour les
145 fonctions sd_prod de commandes et ops de macros ou de contexte
146 d'évaluation des conditions de présence de BLOC.
148 Si l'argument condition de la méthode vaut 1, on ne
149 remonte pas les valeurs des mots clés contenus dans des blocs
150 pour eviter les bouclages.
152 Cette méthode réalise les opérations suivantes en plus de transformer
153 la liste en dictionnaire :
155 - ajouter tous les mots-clés non présents avec la valeur None
156 - ajouter tous les mots-clés globaux (attribut position = 'global'
159 L'argument liste est, en général, une mc_liste en cours de
160 construction, contenant les mots-clés locaux et les blocs déjà créés.
166 # Si v est un BLOC, on inclut ses items dans le dictionnaire
167 # représentatif du contexte. Les blocs sont retournés par get_valeur
168 # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
169 # donc remontés au niveau du contexte.
170 if not condition:dico.update(v.get_valeur())
172 dico[v.nom]=v.get_valeur()
174 # On rajoute tous les autres mots-clés locaux possibles avec la valeur
176 # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d')
178 # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement
180 for k,v in self.definition.entites.items():
181 if not dico.has_key(k):
182 if v.label == 'SIMP':
185 elif v.label == 'FACT' :
186 if v.statut in ('c','d') :
187 # Mot clé facteur avec défaut ou caché provisoire
188 dico[k]=v(val=None,nom=k,parent=self)
189 # On demande la suppression des pointeurs arrieres
190 # pour briser les eventuels cycles
194 # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
195 # valeur par défaut ou la valeur None
197 # On rajoute les mots-clés globaux sans écraser les clés existantes
198 dico_mc = self.recherche_mc_globaux()
204 def cree_dict_condition(self,liste=[],condition=0):
206 Methode pour construire un contexte qui servira dans l'évaluation
207 des conditions de présence de blocs. Si une commande a un concept
208 produit réutilisé, on ajoute la clé 'reuse'
210 dico=self.cree_dict_valeurs(liste,condition=1)
211 # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination
212 # uniquement des commandes. Ne devrait pas etre dans cette classe mais dans une classe dérivée
213 if not dico.has_key('reuse') and hasattr(self,'reuse'):
214 dico['reuse']=self.reuse
217 def recherche_mc_globaux(self):
219 Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
220 et des mots-clés globaux du jdc
222 etape = self.get_etape()
224 dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
225 for k,v in etape.mc_globaux.items():
226 dict_mc_globaux_fac[k]=v.get_valeur()
228 for k,v in self.jdc.mc_globaux.items():
229 dict_mc_globaux_fac[k]=v.get_valeur()
230 return dict_mc_globaux_fac
234 def recherche_mc_globaux_facultatifs(self):
236 Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
237 directs de self de type 'global'
240 etape = self.get_etape()
241 if not etape : return {}
242 for k,v in etape.definition.entites.items():
243 if v.label != 'SIMP' : continue
244 if v.position != 'global' : continue
245 if v.statut == 'o':continue
246 obj = v(val=None,nom=k,parent=etape)
247 dico[k]=obj.get_valeur()
252 Méthode qui supprime toutes les références arrières afin que l'objet puisse
253 etre correctement détruit par le garbage collector
255 N_OBJECT.OBJECT.supprime(self)
256 for child in self.mc_liste :
259 def __getitem__(self,key):
261 Cette méthode retourne la valeur d'un sous mot-clé (key)
263 return self.get_mocle(key)
265 def get_mocle(self,key):
267 Retourne la valeur du sous mot-clé key
268 Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre
269 dans un BLOC fils de self
271 # on cherche dans les mots cles presents, le mot cle de nom key
272 # s'il est là on retourne sa valeur (méthode get_val)
273 for child in self.mc_liste:
274 if child.nom == key : return child.get_val()
275 # Si on n a pas trouve de mot cle present on retourne le defaut
276 # eventuel pour les mots cles accessibles dans la definition
279 d=self.definition.entites[key]
280 if d.label == 'SIMP':
282 elif d.label == 'FACT':
283 # il faut construire les objets necessaires pour
284 # evaluer les conditions des blocs eventuels (a faire)
285 if d.statut == 'o' :return None
286 if d.statut != 'c' and d.statut != 'd' :
289 return d(val=None,nom=key,parent=self)
291 # le mot cle n est pas defini a ce niveau
293 # Si on a toujours rien trouve, on cherche dans les blocs presents
294 # On suppose que tous les blocs possibles ont ete crees meme ceux
295 # induits par un mot cle simple absent avec defaut (???)
296 for mc in self.mc_liste :
297 if not mc.isBLOC() : continue
299 return mc.get_mocle(key)
301 # On n a rien trouve dans ce bloc, on passe au suivant
303 # On a rien trouve, le mot cle est absent.
304 # On leve une exception
305 raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
307 def get_child(self,name,restreint = 'non'):
309 Retourne le fils de self de nom name ou None s'il n'existe pas
310 Si restreint vaut oui : ne regarde que dans la mc_liste
311 Si restreint vaut non : regarde aussi dans les entites possibles
313 (Ce dernier cas n'est utilisé que dans le catalogue)
315 for v in self.mc_liste:
316 if v.nom == name : return v
317 if restreint == 'non' :
319 entite=self.definition.entites[name]
320 if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ( 'c', 'd')):
321 return entite(None,name,None)
327 def append_mc_global(self,mc):
329 Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
331 etape = self.get_etape()
334 etape.mc_globaux[nom]=mc
336 def append_mc_global_jdc(self,mc):
338 Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc
341 self.jdc.mc_globaux[nom]=mc
344 """ Retourne une copie de self """
345 objet = self.makeobjet()
346 # FR : attention !!! avec makeobjet, objet a le meme parent que self
347 # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
348 # FR : peut-on passer par là autrement que dans le cas d'une copie ???
349 # FR --> je suppose que non
350 # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
351 # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
352 objet.valeur = copy(self.valeur)
353 objet.val = copy(self.val)
355 for obj in self.mc_liste:
357 new_obj.reparent(objet)
358 objet.mc_liste.append(new_obj)
361 def reparent(self,parent):
363 Cette methode sert a reinitialiser la parente de l'objet
366 self.jdc=parent.get_jdc_root()
367 self.etape=parent.etape
368 for mocle in self.mc_liste:
371 def get_sd_utilisees(self):
373 Retourne la liste des concepts qui sont utilisés à l'intérieur de self
374 ( comme valorisation d'un MCS)
377 for child in self.mc_liste:
378 l.extend(child.get_sd_utilisees())
381 def get_sd_mcs_utilisees(self):
383 Retourne la ou les SD utilisée par self sous forme d'un dictionnaire :
384 . Si aucune sd n'est utilisée, le dictionnaire est vide.
385 . Sinon, les clés du dictionnaire sont les mots-clés derrière lesquels on
386 trouve des sd ; la valeur est la liste des sd attenante.
387 Exemple : { '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] = daux[cle]
398 def get_mcs_with_co(self,co):
400 Cette methode retourne l'objet MCSIMP fils de self
401 qui a le concept co comme valeur.
402 En principe, elle ne doit etre utilisee que pour les concepts
403 instances de la classe CO
406 for child in self.mc_liste:
407 l.extend(child.get_mcs_with_co(co))
410 def get_all_co(self):
412 Cette methode retourne tous les concepts instances de CO
415 for child in self.mc_liste:
416 l.extend(child.get_all_co())