1 # -*- coding: utf-8 -*-
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 # ======================================================================
27 from Noyau.N_MCLIST import MCList
28 from Noyau.N_MCSIMP import MCSIMP
29 from Noyau.N_MCFACT import MCFACT
30 from Noyau.N_MCBLOC import MCBLOC
35 class MCCOMPO(I_OBJECT.OBJECT):
36 def getlabeltext(self):
38 Retourne le label de self
39 utilisé pour l'affichage dans l'arbre
43 def get_liste_mc_ordonnee(self,liste,dico):
45 Retourne la liste ordonnée (suivant le catalogue) des mots-clés
46 d'une entité composée dont le chemin complet est donné sous forme
47 d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
48 il faut encore réarranger cette liste (certains mots-clés déjà
49 présents ne doivent plus être proposés, règles ...)
51 return self.filtre_liste_mc(self.get_liste_mc_ordonnee_brute(liste,dico))
53 def get_liste_mc_ordonnee_brute(self,liste,dico):
55 Retourne la liste ordonnée (suivant le catalogue) BRUTE des mots-clés
56 d'une entité composée dont le chemin complet est donné sous forme
57 d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
60 objet_cata = dico[arg]
61 dico=objet_cata.entites
62 return objet_cata.ordre_mc
64 def filtre_liste_mc(self,liste_brute):
66 Cette méthode est appelée par EFICAS afin de présenter à
67 l'utilisateur la liste des enfants possibles de self actualisée
68 en fonction du contexte de self. En clair, sont supprimés de la
69 liste des possibles (fournie par la définition), les mots-clés
70 exclus par les règles de self et les mots-clés ne pouvant plus
73 liste = copy(liste_brute)
74 liste_mc_presents = self.liste_mc_presents()
75 # on enlève les mots-clés non permis par les règles
76 for regle in self.definition.regles:
77 # la méthode purge_liste est à développer pour chaque règle qui
78 # influe sur la liste de choix à proposer à l'utilisateur
79 # --> EXCLUS,UN_PARMI,PRESENT_ABSENT
80 liste = regle.purge_liste(liste,liste_mc_presents)
81 # on enlève les mots-clés dont l'occurrence est déjà atteinte
82 liste_copy = copy(liste)
84 objet = self.get_child(k,restreint = 'oui')
86 # l'objet est déjà présent : il faut distinguer plusieurs cas
87 if isinstance(objet,MCSIMP):
88 # un mot-clé simple ne peut pas être répété
90 elif isinstance(objet,MCBLOC):
91 # un bloc conditionnel ne doit pas apparaître dans la liste de choix
93 elif isinstance(objet,MCFACT):
94 # un mot-clé facteur ne peut pas être répété plus de self.max fois
95 if objet.definition.max == 1:
97 elif isinstance(objet,MCList):
99 nb_occur_maxi = objet[0].definition.max
100 if len(objet) >= nb_occur_maxi:
105 #XXX CCAR : les MCNUPLET ne sont pas traités
106 if CONTEXT.debug : print ' ',k,' est un objet de type inconnu :',type(objet)
108 # l'objet est absent : on enlève de la liste les blocs
109 if self.definition.entites[k].statut=='c' :
111 if self.definition.entites[k].label=='BLOC':
113 # Pour corriger les exces qui pourraient etre commis dans la methode purge_liste
114 # des regles, on essaie de compenser comme suit :
115 # on ajoute les mots cles facteurs presents dont l'occurence n'est pas atteinte
116 for k in liste_mc_presents:
117 if k in liste:continue
118 objet = self.get_child(k,restreint = 'oui')
119 if isinstance(objet,MCFACT):
120 # un mot-clé facteur ne peut pas être répété plus de self.max fois
121 if objet.definition.max > 1:
123 elif isinstance(objet,MCList):
124 nb_occur_maxi = objet[0].definition.max
125 if len(objet) < nb_occur_maxi:
129 def liste_mc_presents(self):
131 Retourne la liste des noms des mots-clés fils de self présents construite
132 à partir de self.mc_liste
135 for v in self.mc_liste:
140 def get_index_child(self,nom_fils):
142 Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils
143 Permet de savoir à quelle position il faut ajouter un nouveau mot-clé
145 cata_ordonne = self.jdc.cata_ordonne_dico
146 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(self.get_genealogie(),cata_ordonne)
147 liste_noms_mc_presents = self.liste_mc_presents()
149 for nom in liste_noms_mc_ordonnee:
150 if nom == nom_fils:break
151 if nom not in liste_noms_mc_presents :continue
155 def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
157 Retourne liste_mc_a_ordonner ordonnée suivant l'ordre
158 donné par liste_noms_mc_ordonnee
161 # on transforme liste_a_ordonner en un dictionnaire (plus facile à consulter)
163 for mc in liste_mc_a_ordonner:
165 # on construit la liste des objets ordonnés
166 for nom_mc in liste_noms_mc_ordonnee:
167 if d_mc.has_key(nom_mc):
168 liste.append(d_mc.get(nom_mc))
172 def suppentite(self,objet) :
174 Supprime le fils 'objet' de self :
175 Retourne 1 si la suppression a pu être effectuée,
176 Retourne 0 dans le cas contraire
179 if not objet in self.mc_liste:
180 # Impossible de supprimer objet. Il n'est pas dans mc_liste
185 self.mc_liste.remove(objet)
186 CONNECTOR.Emit(self,"supp",objet)
188 if hasattr(objet.definition,'position'):
189 if objet.definition.position == 'global' :
190 self.delete_mc_global(objet)
191 self.etape.deep_update_condition_bloc()
192 elif objet.definition.position == 'global_jdc' :
193 self.delete_mc_global_jdc(objet)
194 self.jdc.deep_update_condition_bloc()
196 self.update_condition_bloc()
207 def addentite(self,name,pos=None):
209 Ajoute le mot-cle name à la liste des mots-cles de
212 #print "I_MCCOMPO.addentite",name,pos
214 if type(name)==types.StringType :
215 # on est en mode création d'un motcle
216 if self.ispermis(name) == 0 : return 0
217 objet=self.definition.entites[name](val=None,nom=name,parent=self)
218 if hasattr(objet.definition,'position'):
219 if objet.definition.position == 'global' :
220 self.append_mc_global(objet)
221 elif objet.definition.position == 'global_jdc' :
222 self.append_mc_global_jdc(objet)
224 # dans ce cas on est en mode copie d'un motcle
226 # Appel de la methode qui fait le menage dans les references
227 # sur les concepts produits (verification que les concepts existent
228 # dans le contexte de la commande courante).
229 objet.verif_existence_sd()
231 # On verifie que l'ajout d'objet est autorise
232 if self.ispermis(objet) == 0:
233 self.jdc.send_message("L'objet %s ne peut être un fils de %s" %(objet.nom,
238 # On cherche s'il existe deja un mot cle de meme nom
239 old_obj = self.get_child(objet.nom,restreint = 'oui')
240 #print "addentite",old_obj
241 #if old_obj:print "addentite",old_obj.isrepetable(),old_obj.isMCList(),old_obj.ajout_possible()
243 #print self.mc_liste,objet
244 # Le mot cle n'existe pas encore. On l'ajoute a la position
247 self.mc_liste.append(objet)
249 self.mc_liste.insert(pos,objet)
250 #print self.mc_liste,objet
251 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
253 CONNECTOR.Emit(self,"add",objet)
257 # Le mot cle existe deja. Si le mot cle est repetable,
258 # on cree une liste d'objets. Dans le cas contraire,
259 # on emet un message d'erreur.
260 if not old_obj.isrepetable():
261 self.jdc.send_message("L'objet %s ne peut pas être répété" %objet.nom)
265 if not old_obj.isMCList():
266 # un objet de même nom existe déjà mais ce n'est pas une MCList
267 # Il faut en créer une
268 # L'objet existant (old_obj) est certainement un MCFACT
269 # qui pointe vers un constructeur
270 # de MCList : definition.liste_instance
271 index = self.mc_liste.index(old_obj)
272 new_obj = old_obj.definition.list_instance()
273 new_obj.init(objet.nom,self)
274 new_obj.append(old_obj)
275 new_obj.append(objet)
276 # Il ne faut pas oublier de reaffecter le parent d'obj
278 self.mc_liste.remove(old_obj)
279 CONNECTOR.Emit(self,"supp",old_obj)
280 self.mc_liste.insert(index,new_obj)
281 CONNECTOR.Emit(self,"add",new_obj)
285 # une liste d'objets de même type existe déjà
286 old_obj.addentite(objet)
289 def ispermis(self,fils):
291 Retourne 1 si l'objet de nom nom_fils
292 est bien permis, cad peut bien être un fils de self,
295 if type(fils) == types.StringType :
296 # on veut juste savoir si self peut avoir un fils de nom 'fils'
297 if self.definition.entites.has_key(fils):
301 elif type(fils) == types.InstanceType:
302 # fils est un objet (commande,mcf,mclist)
303 # on est dans le cas d'une tentative de copie de l'objet
304 # on veut savoir si l'objet peut bien être un fils de self :
305 # la vérification du nom de suffit pas (plusieurs commandes
306 # ont le même mot-clé facteur AFFE ... et c'est l'utilisateur
307 # qui choisit le père d'où un risque d'erreur)
308 if not self.definition.entites.has_key(fils.nom):
311 if fils.parent.nom != self.nom : return 0
314 def update_concept(self,sd):
315 for child in self.mc_liste :
316 child.update_concept(sd)
318 def delete_concept(self,sd):
323 Mettre a jour les fils de l objet suite à la disparition du
325 Seuls les mots cles simples MCSIMP font un traitement autre que
326 de transmettre aux fils
328 for child in self.mc_liste :
329 child.delete_concept(sd)
331 def replace_concept(self,old_sd,sd):
334 - old_sd=concept remplace
335 - sd = nouveau concept
337 Mettre a jour les fils de l objet suite au remplacement du
340 for child in self.mc_liste :
341 child.replace_concept(old_sd,sd)
343 def delete_mc_global(self,mc):
345 Supprime le mot-clé mc de la liste des mots-clés globaux de l'étape
347 etape = self.get_etape()
350 del etape.mc_globaux[nom]
352 def delete_mc_global_jdc(self,mc):
354 Supprime le mot-clé mc de la liste des mots-clés globaux du jdc
357 del self.jdc.mc_globaux[nom]
359 def get_liste_mc_inconnus(self):
361 Retourne la liste des mots-clés inconnus dans self
364 if self.reste_val != {}:
365 for k,v in self.reste_val.items() :
366 l_mc.append([self,k,v])
367 for child in self.mc_liste :
368 if child.isvalid() : continue
369 l_child = child.get_liste_mc_inconnus()
376 def deep_update_condition_bloc(self):
378 Parcourt l'arborescence des mcobject et realise l'update
379 des blocs conditionnels par appel de la methode update_condition_bloc
381 #print "deep_update_condition_bloc",self
382 self.update_condition_bloc()
383 for mcobj in self.mc_liste:
384 if hasattr(mcobj,"deep_update_condition_bloc"):
385 mcobj.deep_update_condition_bloc()
387 def update_condition_bloc(self):
389 Realise l'update des blocs conditionnels fils de self
391 #print "update_condition_bloc",self
392 dict = self.cree_dict_condition(self.mc_liste,condition=1)
393 for k,v in self.definition.entites.items():
394 if v.label != 'BLOC' :continue
395 globs= self.jdc and self.jdc.condition_context or {}
396 bloc=self.get_child(k,restreint = 'oui')
397 presence=v.verif_presence(dict,globs)
398 if presence and not bloc:
399 # le bloc doit être présent
400 # mais le bloc n'est pas présent et il doit être créé
401 #print "AJOUT BLOC",k
402 pos=self.get_index_child(k)
403 self.addentite(k,pos)
404 if not presence and bloc:
405 # le bloc devrait être absent
406 # le bloc est présent : il faut l'enlever
407 #print "SUPPRESSION BLOC",k,bloc
408 self.suppentite(bloc)
410 def verif_condition_bloc(self):
412 Evalue les conditions de tous les blocs fils possibles
413 (en fonction du catalogue donc de la définition) de self
414 et retourne deux listes :
415 - la première contient les noms des blocs à rajouter
416 - la seconde contient les noms des blocs à supprimer
420 dict = self.cree_dict_condition(self.mc_liste,condition=1)
421 for k,v in self.definition.entites.items():
423 globs= self.jdc and self.jdc.condition_context or {}
424 if v.verif_presence(dict,globs):
425 # le bloc doit être présent
426 if not self.get_child(k,restreint = 'oui'):
427 # le bloc n'est pas présent et il doit être créé
428 liste_ajouts.append(k)
430 # le bloc doit être absent
431 if self.get_child(k,restreint = 'oui'):
432 # le bloc est présent : il faut l'enlever
433 liste_retraits.append(k)
434 return liste_ajouts,liste_retraits
436 def verif_existence_sd(self):
438 Vérifie que les structures de données utilisées dans self existent bien dans le contexte
439 avant étape, sinon enlève la référence à ces concepts
441 for motcle in self.mc_liste :
442 motcle.verif_existence_sd()