1 # -*- coding: utf-8 -*-
2 #@ MODIF N_MCCOMPO Noyau DATE 04/02/2004 AUTEUR CAMBIER S.CAMBIER
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 # ======================================================================
23 Ce module contient la classe MCCOMPO qui sert à factoriser les comportements
31 class MCCOMPO(N_OBJECT.OBJECT):
33 Classe support d'un OBJECT composite
39 Construit la liste des sous-entites du MCCOMPO
40 à partir du dictionnaire des arguments (valeur)
42 if CONTEXT.debug : print "MCCOMPO.build_mc ",self.nom
43 # Dans la phase de reconstruction args peut contenir des mots-clés
44 # qui ne sont pas dans le dictionnaire des entites de definition (self.definition.entites)
45 # de l'objet courant (self)
46 # mais qui sont malgré tout des descendants de l'objet courant (petits-fils, ...)
48 if args == None : args ={}
51 # On recopie le dictionnaire des arguments pour protéger l'original des delete (del args[k])
55 # On construit les sous entites presentes ou obligatoires
56 # 1- les entites présentes dans les arguments et dans la définition
57 # 2- les entités non présentes dans les arguments, présentes dans la définition avec un défaut
58 for k,v in self.definition.entites.items():
59 if args.has_key(k) or v.statut=='o' :
61 # Creation par appel de la methode __call__ de la definition de la sous entite k de self
62 # si une valeur existe dans args ou est obligatoire (generique si toutes les
63 # entites ont l attribut statut )
65 objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
66 mc_liste.append(objet)
67 # Si l'objet a une position globale on l'ajoute aux listes correspondantes
68 if hasattr(objet.definition,'position'):
69 if objet.definition.position == 'global' :
70 self.append_mc_global(objet)
71 elif objet.definition.position == 'global_jdc' :
72 self.append_mc_global_jdc(objet)
77 # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés.
78 # A ce stade, mc_liste ne contient que les fils de l'objet courant
79 # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont
80 # à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés
81 dico_valeurs = self.cree_dict_condition(mc_liste,condition=1)
82 for k,v in self.definition.entites.items():
83 if v.label != 'BLOC':continue
84 # condition and a or b : Equivalent de l'expression : condition ? a : b du langage C
85 globs= self.jdc and self.jdc.condition_context or {}
86 if v.verif_presence(dico_valeurs,globs):
89 # 2- on l'ajoute à mc_liste
90 # 3- on récupère les arguments restant
91 # 4- on reconstruit le dictionnaire équivalent à mc_liste
92 bloc = v(nom=k,val=args,parent=self)
95 # On ne recalcule pas le contexte car on ne tient pas compte des blocs
96 # pour évaluer les conditions de présence des blocs
97 #dico_valeurs = self.cree_dict_valeurs(mc_liste)
99 # On conserve les arguments superflus dans l'attribut reste_val
101 # On ordonne la liste ainsi créée suivant l'ordre du catalogue
102 # (utile seulement pour IHM graphique)
103 mc_liste = self.ordonne_liste(mc_liste)
104 # on retourne la liste ainsi construite
107 def ordonne_liste(self,mc_liste):
109 Ordonne la liste suivant l'ordre du catalogue.
110 Seulement pour IHM graphique
112 if self.jdc and self.jdc.cata_ordonne_dico != None :
113 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(
114 self.get_genealogie(),self.jdc.cata_ordonne_dico)
115 return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee)
119 def cree_dict_valeurs(self,liste=[],condition=0):
121 Cette méthode crée un contexte (sous la forme d'un dictionnaire)
122 à partir des valeurs des mots clés contenus dans l'argument liste.
123 L'opération consiste à parcourir la liste (d'OBJECT) et à la
124 transformer en un dictionnaire dont les clés sont les noms des
125 mots clés et les valeurs dépendent du type d'OBJECT.
126 Ce dictionnaire servira de liste d'arguments d'appel pour les
127 fonctions sd_prod de commandes et ops de macros ou de contexte
128 d'évaluation des conditions de présence de BLOC.
130 Si l'argument condition de la méthode vaut 1, on ne
131 remonte pas les valeurs des mots clés contenus dans des blocs
132 pour eviter les bouclages.
134 Cette méthode réalise les opérations suivantes en plus de transformer
135 la liste en dictionnaire :
137 - ajouter tous les mots-clés non présents avec la valeur None
138 - ajouter tous les mots-clés globaux (attribut position = 'global'
141 L'argument liste est, en général, une mc_liste en cours de
142 construction, contenant les mots-clés locaux et les blocs déjà créés.
148 # Si v est un BLOC, on inclut ses items dans le dictionnaire
149 # représentatif du contexte. Les blocs sont retournés par get_valeur
150 # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
151 # donc remontés au niveau du contexte.
152 if not condition:dico.update(v.get_valeur())
154 dico[v.nom]=v.get_valeur()
156 # On rajoute tous les autres mots-clés locaux possibles avec la valeur
158 # Pour les mots-clés facteurs, on ne traite que ceux avec statut défaut ('d')
160 # On n'ajoute aucune information sur les blocs. Ils n'ont pas de défaut seulement
162 for k,v in self.definition.entites.items():
163 if not dico.has_key(k):
164 if v.label == 'SIMP':
167 elif v.label == 'FACT' :
168 if v.statut in ('c','d') :
169 # Mot clé facteur avec défaut ou caché provisoire
170 dico[k]=v(val=None,nom=k,parent=self)
171 # On demande la suppression des pointeurs arrieres
172 # pour briser les eventuels cycles
176 # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
177 # valeur par défaut ou la valeur None
179 # On rajoute les mots-clés globaux sans écraser les clés existantes
180 dico_mc = self.recherche_mc_globaux()
186 def cree_dict_condition(self,liste=[],condition=0):
188 Methode pour construire un contexte qui servira dans l'évaluation
189 des conditions de présence de blocs. Si une commande a un concept
190 produit réutilisé, on ajoute la clé 'reuse'
192 dico=self.cree_dict_valeurs(liste,condition=1)
193 # On ajoute la cle "reuse" pour les MCCOMPO qui ont un attribut reuse. A destination
194 # uniquement des commandes. Ne devrait pas etre dans cette classe mais dans une classe dérivée
195 if not dico.has_key('reuse') and hasattr(self,'reuse'):
196 dico['reuse']=self.reuse
199 def recherche_mc_globaux(self):
201 Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
202 et des mots-clés globaux du jdc
204 etape = self.get_etape()
206 dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
207 dict_mc_globaux_fac.update(etape.mc_globaux)
208 if self.jdc : dict_mc_globaux_fac.update(self.jdc.mc_globaux)
209 return dict_mc_globaux_fac
213 def recherche_mc_globaux_facultatifs(self):
215 Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
216 directs de self de type 'global'
219 etape = self.get_etape()
220 if not etape : return {}
221 for k,v in etape.definition.entites.items():
222 if v.label != 'SIMP' : continue
223 if v.position != 'global' : continue
224 if v.statut == 'o':continue
225 obj = v(val=None,nom=k,parent=etape)
231 Méthode qui supprime toutes les références arrières afin que l'objet puisse
232 etre correctement détruit par le garbage collector
234 N_OBJECT.OBJECT.supprime(self)
235 for child in self.mc_liste :
238 def __getitem__(self,key):
240 Cette méthode retourne la valeur d'un sous mot-clé (key)
242 return self.get_mocle(key)
244 def get_mocle(self,key):
246 Retourne la valeur du sous mot-clé key
247 Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre
248 dans un BLOC fils de self
250 # on cherche dans les mots cles presents, le mot cle de nom key
251 # s'il est là on retourne sa valeur (méthode get_val)
252 for child in self.mc_liste:
253 if child.nom == key : return child.get_val()
254 # Si on n a pas trouve de mot cle present on retourne le defaut
255 # eventuel pour les mots cles accessibles dans la definition
258 d=self.definition.entites[key]
259 if d.label == 'SIMP':
261 elif d.label == 'FACT':
262 # il faut construire les objets necessaires pour
263 # evaluer les conditions des blocs eventuels (a faire)
264 if d.statut == 'o' :return None
265 if d.statut != 'c' and d.statut != 'd' :
268 return d(val=None,nom=key,parent=self)
270 # le mot cle n est pas defini a ce niveau
272 # Si on a toujours rien trouve, on cherche dans les blocs presents
273 # On suppose que tous les blocs possibles ont ete crees meme ceux
274 # induits par un mot cle simple absent avec defaut (???)
275 for mc in self.mc_liste :
276 if not mc.isBLOC() : continue
278 return mc.get_mocle(key)
280 # On n a rien trouve dans ce bloc, on passe au suivant
282 # On a rien trouve, le mot cle est absent.
283 # On leve une exception
284 raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
286 def get_child(self,name,restreint = 'non'):
288 Retourne le fils de self de nom name ou None s'il n'existe pas
289 Si restreint vaut oui : ne regarde que dans la mc_liste
290 Si restreint vaut non : regarde aussi dans les entites possibles
292 (Ce dernier cas n'est utilisé que dans le catalogue)
294 for v in self.mc_liste:
295 if v.nom == name : return v
296 if restreint == 'non' :
298 entite=self.definition.entites[name]
299 if entite.label == 'SIMP' or (entite.label == 'FACT' and entite.statut in ( 'c', 'd')):
300 return entite(None,name,None)
306 def append_mc_global(self,mc):
308 Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
310 etape = self.get_etape()
313 etape.mc_globaux[nom]=mc
315 def append_mc_global_jdc(self,mc):
317 Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc
320 self.jdc.mc_globaux[nom]=mc
323 """ Retourne une copie de self """
324 objet = self.makeobjet()
325 # FR : attention !!! avec makeobjet, objet a le meme parent que self
326 # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
327 # FR : peut-on passer par là autrement que dans le cas d'une copie ???
328 # FR --> je suppose que non
329 # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
330 # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
331 objet.valeur = copy(self.valeur)
332 objet.val = copy(self.val)
334 for obj in self.mc_liste:
336 new_obj.reparent(objet)
337 objet.mc_liste.append(new_obj)
340 def reparent(self,parent):
342 Cette methode sert a reinitialiser la parente de l'objet
345 self.jdc=parent.get_jdc_root()
346 self.etape=parent.etape
347 for mocle in self.mc_liste:
350 def get_sd_utilisees(self):
352 Retourne la liste des concepts qui sont utilisés à l'intérieur de self
353 ( comme valorisation d'un MCS)
356 for child in self.mc_liste:
357 l.extend(child.get_sd_utilisees())