2 Ce module contient la classe MCCOMPO qui sert à factoriser les comportements
10 class MCCOMPO(N_OBJECT.OBJECT):
12 Classe support d'un OBJECT composite
18 Construit la liste des sous-entites du MCCOMPO
19 à partir du dictionnaire des arguments (valeur)
21 if CONTEXT.debug : print "MCCOMPO.build_mc ",self.nom
22 # Dans la phase de reconstruction args peut contenir des mots-clés
23 # qui ne sont pas dans le dictionnaire des entites de definition (self.definition.entites)
24 # de l'objet courant (self)
25 # mais qui sont malgré tout des descendants de l'objet courant (petits-fils, ...)
27 if args == None : args ={}
30 # On recopie le dictionnaire des arguments pour protéger l'original des delete (del args[k])
34 # On construit les sous entites presentes ou obligatoires
35 # 1- les entites présentes dans les arguments et dans la définition
36 # 2- les entités non présentes dans les arguments, présentes dans la définition avec un défaut
37 for k,v in self.definition.entites.items():
38 if args.has_key(k) or v.statut=='o' :
40 # Creation par appel de la methode __call__ de la definition de la sous entite k de self
41 # si une valeur existe dans args ou est obligatoire (generique si toutes les
42 # entites ont l attribut statut )
44 objet=self.definition.entites[k](val=args.get(k,None),nom=k,parent=self)
45 mc_liste.append(objet)
46 # Si l'objet a une position globale on l'ajoute aux listes correspondantes
47 if hasattr(objet.definition,'position'):
48 if objet.definition.position == 'global' :
49 self.append_mc_global(objet)
50 elif objet.definition.position == 'global_jdc' :
51 self.append_mc_global_jdc(objet)
56 # On construit les objets (en général, blocs) conditionnés par les mots-clés précédemment créés.
57 # A ce stade, mc_liste ne contient que les fils de l'objet courant
58 # args ne contient plus que des mots-clés qui n'ont pas été attribués car ils sont
59 # à attribuer à des blocs du niveau inférieur ou bien sont des mots-clés erronés
60 dico_valeurs = self.cree_dict_valeurs(mc_liste)
61 for k,v in self.definition.entites.items():
62 if v.label != 'BLOC':continue
63 if v.verif_presence(dico_valeurs):
66 # 2- on l'ajoute à mc_liste
67 # 3- on récupère les arguments restant
68 # 4- on reconstruit le dictionnaire équivalent à mc_liste
69 bloc = v(nom=k,val=args,parent=self)
72 dico_valeurs = self.cree_dict_valeurs(mc_liste)
74 # On conserve les arguments superflus dans l'attribut reste_val
76 # On ordonne la liste ainsi créée suivant l'ordre du catalogue
77 # (utile seulement pour IHM graphique)
78 mc_liste = self.ordonne_liste(mc_liste)
79 # on retourne la liste ainsi construite
82 def ordonne_liste(self,mc_liste):
84 Ordonne la liste suivant l'ordre du catalogue.
85 Seulement pour IHM graphique
87 if self.jdc and self.jdc.cata_ordonne_dico != None :
88 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(
89 self.get_genealogie(),self.jdc.cata_ordonne_dico)
90 return self.ordonne_liste_mc(mc_liste,liste_noms_mc_ordonnee)
94 def cree_dict_valeurs(self,liste=[]):
96 Cette méthode crée le contexte de l'objet courant sous la forme
98 L'opération consiste à transformer une liste d'OBJECT en un
100 Ce dictionnaire servira de contexte pour évaluer les conditions des
103 Cette méthode réalise les opérations suivantes en plus de transformer
104 la liste en dictionnaire :
106 - ajouter tous les mots-clés non présents avec la valeur None
108 - ajouter tous les mots-clés globaux (attribut position = 'global'
111 ATTENTION : -- on ne remonte pas (semble en contradiction avec la
112 programmation de la méthode get_valeur du bloc) les
113 mots-clé fils d'un bloc au niveau du
114 contexte car celà peut générer des erreurs.
116 L'argument liste est, en général, une mc_liste en cours de
117 construction, contenant les mots-clés locaux et les blocs déjà créés.
124 # Si val est un dictionnaire, on inclut ses items dans le dictionnaire
125 # représentatif du contexte. Les blocs sont retournés par get_valeur
126 # sous la forme d'un dictionnaire : les mots-clés fils de blocs sont
127 # donc remontés au niveau du contexte.
128 if type(val)==types.DictionaryType:
129 for i,w in val.items():
133 # on rajoute tous les autres mots-clés locaux possibles avec la valeur
135 # Pour les mots-clés facteurs, on ne tient pas compte du défaut
137 for k,v in self.definition.entites.items():
138 if not dico.has_key(k):
139 if v.label == 'SIMP':
141 # S il est declare global il n est pas necessaire de l ajouter
142 # aux mots cles globaux de l'etape
143 # car la methode recherche_mc_globaux les rajoutera
144 elif v.label == 'FACT' and v.statut in ('c','d') :
145 dico[k]=v(val=None,nom=k,parent=self)
146 # On demande la suppression des pointeurs arrieres
147 # pour briser les eventuels cycles
149 elif v.label != 'BLOC':
151 # A ce stade on a rajouté tous les mots-clés locaux possibles (fils directs) avec leur
152 # valeur par défaut ou la valeur None
153 # on rajoute les mots-clés globaux ...
154 dico_mc = self.recherche_mc_globaux()
155 for nom,mc in dico_mc.items() :
156 if not dico.has_key(nom) : dico[nom]=mc.valeur
157 # Il nous reste à évaluer la présence des blocs en fonction du contexte qui a changé
158 for k,v in self.definition.entites.items():
159 if v.label != 'BLOC' : continue
160 if v.verif_presence(dico):
161 # le bloc k doit être présent : on crée temporairement l'objet MCBLOC correspondant
162 # on lui passe un parent égal à None pour qu'il ne soit pas enregistré
163 bloc = v(nom=k,val=None,parent=None)
164 dico_bloc = bloc.cree_dict_valeurs()
166 # on va updater dico avec dico_bloc en veillant à ne pas écraser
167 # des valeurs déjà présentes
168 for cle in dico_bloc.keys():
169 if not dico.has_key(cle):
170 dico[cle]=dico_bloc[cle]
173 def recherche_mc_globaux(self):
175 Retourne la liste des mots-clés globaux de l'étape à laquelle appartient self
176 et des mots-clés globaux du jdc
178 etape = self.get_etape()
180 dict_mc_globaux_fac = self.recherche_mc_globaux_facultatifs()
181 dict_mc_globaux_fac.update(etape.mc_globaux)
182 if self.jdc : dict_mc_globaux_fac.update(self.jdc.mc_globaux)
183 return dict_mc_globaux_fac
187 def recherche_mc_globaux_facultatifs(self):
189 Cette méthode interroge la définition de self et retourne la liste des mots-clés fils
190 directs de self de type 'global'
193 etape = self.get_etape()
194 if not etape : return {}
195 for k,v in etape.definition.entites.items():
196 if v.label != 'SIMP' : continue
197 if v.position != 'global' : continue
198 if v.statut == 'o':continue
199 obj = v(val=None,nom=k,parent=etape)
205 Méthode qui supprime toutes les références arrières afin que l'objet puisse
206 être correctement détruit par le garbage collector
208 N_OBJECT.OBJECT.supprime(self)
209 for child in self.mc_liste :
212 def __getitem__(self,key):
214 Cette méthode retourne la valeur d'un sous mot-clé (key)
216 return self.get_mocle(key)
218 def get_mocle(self,key):
220 Retourne la valeur du sous mot-clé key
221 Ce sous mot-clé peut exister, avoir une valeur par defaut ou etre
222 dans un BLOC fils de self
224 # on cherche dans les mots cles presents, le mot cle de nom key
225 # s'il est là on retourne sa valeur (méthode get_val)
226 for child in self.mc_liste:
227 if child.nom == key : return child.get_val()
228 # Si on n a pas trouve de mot cle present on retourne le defaut
229 # eventuel pour les mots cles accessibles dans la definition
232 d=self.definition.entites[key]
233 if d.label == 'SIMP':
235 elif d.label == 'FACT':
236 # il faut construire les objets necessaires pour
237 # evaluer les conditions des blocs eventuels (a faire)
238 if d.statut == 'o' :return None
239 if d.statut != 'c' and d.statut != 'd' :
242 return d(val=None,nom=key,parent=self)
244 # le mot cle n est pas defini a ce niveau
246 # Si on a toujours rien trouve, on cherche dans les blocs presents
247 # On suppose que tous les blocs possibles ont ete crees meme ceux
248 # induits par un mot cle simple absent avec defaut (???)
249 for mc in self.mc_liste :
250 if not mc.isBLOC() : continue
252 return mc.get_mocle(key)
254 # On n a rien trouve dans ce bloc, on passe au suivant
256 # On a rien trouve, le mot cle est absent.
257 # On leve une exception
258 raise IndexError,"Le mot cle %s n existe pas dans %s" % (key,self)
260 def get_child(self,name,restreint = 'non'):
262 Retourne le fils de self de nom name ou None s'il n'existe pas
263 Si restreint vaut oui : ne regarde que dans la mc_liste
264 Si restreint vaut non : regarde aussi dans les entites possibles
266 (Ce dernier cas n'est utilisé que dans le catalogue)
268 for v in self.mc_liste:
269 if v.nom == name : return v
270 if restreint == 'non' :
271 for k,v in self.definition.entites.items():
273 if v.valeur != None : return v(None,k,None)
276 def append_mc_global(self,mc):
278 Ajoute le mot-clé mc à la liste des mots-clés globaux de l'étape
280 etape = self.get_etape()
283 etape.mc_globaux[nom]=mc
285 def append_mc_global_jdc(self,mc):
287 Ajoute le mot-clé mc à la liste des mots-clés globaux du jdc
290 self.jdc.mc_globaux[nom]=mc