1 #@ MODIF N_MCCOMPO Noyau DATE 04/02/2004 AUTEUR CAMBIER S.CAMBIER
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_condition(mc_liste,condition=1)
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 # On ne recalcule pas le contexte car on ne tient pas compte des blocs
95 # pour évaluer les conditions de présence des blocs
96 #dico_valeurs = self.cree_dict_valeurs(mc_liste)
98 # On conserve les arguments superflus dans l'attribut reste_val
100 # On ordonne la liste ainsi créée suivant l'ordre du catalogue
101 # (utile seulement pour IHM graphique)
102 mc_liste = self.ordonne_liste(mc_liste)
103 # on retourne la liste ainsi construite
106 def ordonne_liste(self,mc_liste):
108 Ordonne la liste suivant l'ordre du catalogue.
109 Seulement pour IHM graphique
111 if self.jdc and self.jdc.cata_ordonne_dico != None :
112 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(
113 self.get_genealogie(),self.jdc.cata_ordonne_dico)
114 return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee)
118 def cree_dict_valeurs(self,liste=[],condition=0):
120 Cette méthode crée un contexte (sous la forme d'un dictionnaire)
121 à partir des valeurs des mots clés contenus dans l'argument liste.
122 L'opération consiste à parcourir la liste (d'OBJECT) et à la
123 transformer en un dictionnaire dont les clés sont les noms des
124 mots clés et les valeurs dépendent du type d'OBJECT.
125 Ce dictionnaire servira de liste d'arguments d'appel pour les
126 fonctions sd_prod de commandes et ops de macros ou de contexte
127 d'évaluation des conditions de présence de BLOC.
129 Si l'argument condition de la méthode vaut 1, on ne
130 remonte pas les valeurs des mots clés contenus dans des blocs
131 pour eviter les bouclages.
133 Cette méthode réalise les opérations suivantes en plus de transformer
134 la liste en dictionnaire :
136 - ajouter tous les mots-clés non présents avec la valeur None
137 - ajouter tous les mots-clés globaux (attribut position = 'global'
140 L'argument liste est, en général, une mc_liste en cours de
141 construction, contenant les mots-clés locaux et les blocs déjà créés.
147 # Si v est un BLOC, on inclut ses items dans le dictionnaire
148 # représentatif du contexte. Les blocs sont retournés par get_valeur
149 # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
150 # donc remontés au niveau du contexte.
151 if not condition:dico.update(v.get_valeur())
153 dico[v.nom]=v.get_valeur()
155 # On rajoute tous les autres mots-clés locaux possibles avec la valeur
157 # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d')
159 # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement
161 for k,v in self.definition.entites.items():
162 if not dico.has_key(k):
163 if v.label == 'SIMP':
166 elif v.label == 'FACT' :
167 if v.statut in ('c','d') :
168 # Mot clé facteur avec défaut ou caché provisoire
169 dico[k]=v(val=None,nom=k,parent=self)
170 # On demande la suppression des pointeurs arrieres
171 # pour briser les eventuels cycles
175 # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
176 # valeur par défaut ou la valeur None
178 # On rajoute les mots-clés globaux sans écraser les clés existantes
179 dico_mc = self.recherche_mc_globaux()
185 def cree_dict_condition(self,liste=[],condition=0):
187 Methode pour construire un contexte qui servira dans l'évaluation
188 des conditions de présence de blocs. Si une commande a un concept
189 produit réutilisé, on ajoute la clé 'reuse'
191 dico=self.cree_dict_valeurs(liste,condition=1)
192 # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination
193 # uniquement des commandes. Ne devrait pas etre dans cette classe mais dans une classe dérivée
194 if not dico.has_key('reuse') and hasattr(self,'reuse'):
195 dico['reuse']=self.reuse
198 def recherche_mc_globaux(self):
200 Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
201 et des mots-clés globaux du jdc
203 etape = self.get_etape()
205 dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
206 dict_mc_globaux_fac.update(etape.mc_globaux)
207 if self.jdc : dict_mc_globaux_fac.update(self.jdc.mc_globaux)
208 return dict_mc_globaux_fac
212 def recherche_mc_globaux_facultatifs(self):
214 Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
215 directs de self de type 'global'
218 etape = self.get_etape()
219 if not etape : return {}
220 for k,v in etape.definition.entites.items():
221 if v.label != 'SIMP' : continue
222 if v.position != 'global' : continue
223 if v.statut == 'o':continue
224 obj = v(val=None,nom=k,parent=etape)
230 Méthode qui supprime toutes les références arrières afin que l'objet puisse
231 etre correctement détruit par le garbage collector
233 N_OBJECT.OBJECT.supprime(self)
234 for child in self.mc_liste :
237 def __getitem__(self,key):
239 Cette méthode retourne la valeur d'un sous mot-clé (key)
241 return self.get_mocle(key)
243 def get_mocle(self,key):
245 Retourne la valeur du sous mot-clé key
246 Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre
247 dans un BLOC fils de self
249 # on cherche dans les mots cles presents, le mot cle de nom key
250 # s'il est là on retourne sa valeur (méthode get_val)
251 for child in self.mc_liste:
252 if child.nom == key : return child.get_val()
253 # Si on n a pas trouve de mot cle present on retourne le defaut
254 # eventuel pour les mots cles accessibles dans la definition
257 d=self.definition.entites[key]
258 if d.label == 'SIMP':
260 elif d.label == 'FACT':
261 # il faut construire les objets necessaires pour
262 # evaluer les conditions des blocs eventuels (a faire)
263 if d.statut == 'o' :return None
264 if d.statut != 'c' and d.statut != 'd' :
267 return d(val=None,nom=key,parent=self)
269 # le mot cle n est pas defini a ce niveau
271 # Si on a toujours rien trouve, on cherche dans les blocs presents
272 # On suppose que tous les blocs possibles ont ete crees meme ceux
273 # induits par un mot cle simple absent avec defaut (???)
274 for mc in self.mc_liste :
275 if not mc.isBLOC() : continue
277 return mc.get_mocle(key)
279 # On n a rien trouve dans ce bloc, on passe au suivant
281 # On a rien trouve, le mot cle est absent.
282 # On leve une exception
283 raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
285 def get_child(self,name,restreint = 'non'):
287 Retourne le fils de self de nom name ou None s'il n'existe pas
288 Si restreint vaut oui : ne regarde que dans la mc_liste
289 Si restreint vaut non : regarde aussi dans les entites possibles
291 (Ce dernier cas n'est utilisé que dans le catalogue)
293 for v in self.mc_liste:
294 if v.nom == name : return v
295 if restreint == 'non' :
297 entite=self.definition.entites[name]
298 if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ( 'c', 'd')):
299 return entite(None,name,None)
305 def append_mc_global(self,mc):
307 Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
309 etape = self.get_etape()
312 etape.mc_globaux[nom]=mc
314 def append_mc_global_jdc(self,mc):
316 Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc
319 self.jdc.mc_globaux[nom]=mc
322 """ Retourne une copie de self """
323 objet = self.makeobjet()
324 # FR : attention !!! avec makeobjet, objet a le meme parent que self
325 # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
326 # FR : peut-on passer par là autrement que dans le cas d'une copie ???
327 # FR --> je suppose que non
328 # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
329 # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
330 objet.valeur = copy(self.valeur)
331 objet.val = copy(self.val)
333 for obj in self.mc_liste:
335 new_obj.reparent(objet)
336 objet.mc_liste.append(new_obj)
339 def reparent(self,parent):
341 Cette methode sert a reinitialiser la parente de l'objet
344 self.jdc=parent.get_jdc_root()
345 self.etape=parent.etape
346 for mocle in self.mc_liste:
349 def get_sd_utilisees(self):
351 Retourne la liste des concepts qui sont utilisés à l'intérieur de self
352 ( comme valorisation d'un MCS)
355 for child in self.mc_liste:
356 l.extend(child.get_sd_utilisees())