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 # ======================================================================
23 import string,types,sys
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
36 class MCCOMPO(I_OBJECT.OBJECT):
37 def getlabeltext(self):
39 Retourne le label de self
40 utilisé pour l'affichage dans l'arbre
44 def get_liste_mc_ordonnee(self,liste,dico):
46 Retourne la liste ordonnée (suivant le catalogue) des mots-clés
47 d'une entité composée dont le chemin complet est donné sous forme
48 d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
49 il faut encore réarranger cette liste (certains mots-clés déjà
50 présents ne doivent plus être proposés, règles ...)
52 return self.filtre_liste_mc(self.get_liste_mc_ordonnee_brute(liste,dico))
54 def get_liste_mc_ordonnee_brute(self,liste,dico):
56 Retourne la liste ordonnée (suivant le catalogue) BRUTE des mots-clés
57 d'une entité composée dont le chemin complet est donné sous forme
58 d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
61 objet_cata = dico[arg]
62 dico=objet_cata.entites
63 return objet_cata.ordre_mc
65 def filtre_liste_mc(self,liste_brute):
67 Cette méthode est appelée par EFICAS afin de présenter à
68 l'utilisateur la liste des enfants possibles de self actualisée
69 en fonction du contexte de self. En clair, sont supprimés de la
70 liste des possibles (fournie par la définition), les mots-clés
71 exclus par les règles de self et les mots-clés ne pouvant plus
74 liste = copy(liste_brute)
75 liste_mc_presents = self.liste_mc_presents()
76 # on enlève les mots-clés non permis par les règles
77 for regle in self.definition.regles:
78 # la méthode purge_liste est à développer pour chaque règle qui
79 # influe sur la liste de choix à proposer à l'utilisateur
80 # --> EXCLUS,UN_PARMI,PRESENT_ABSENT
81 liste = regle.purge_liste(liste,liste_mc_presents)
82 # on enlève les mots-clés dont l'occurrence est déjà atteinte
83 liste_copy = copy(liste)
85 objet = self.get_child(k,restreint = 'oui')
87 # l'objet est déjà présent : il faut distinguer plusieurs cas
88 if isinstance(objet,MCSIMP):
89 # un mot-clé simple ne peut pas être répété
91 elif isinstance(objet,MCBLOC):
92 # un bloc conditionnel ne doit pas apparaître dans la liste de choix
94 elif isinstance(objet,MCFACT):
95 # un mot-clé facteur ne peut pas être répété plus de self.max fois
96 if objet.definition.max == 1:
98 elif isinstance(objet,MCList):
100 nb_occur_maxi = objet[0].definition.max
101 if len(objet) >= nb_occur_maxi:
106 #XXX CCAR : les MCNUPLET ne sont pas traités
107 if CONTEXT.debug : print ' ',k,' est un objet de type inconnu :',type(objet)
109 # l'objet est absent : on enlève de la liste les blocs
110 if self.definition.entites[k].statut=='c' :
112 if self.definition.entites[k].label=='BLOC':
114 # Pour corriger les exces qui pourraient etre commis dans la methode purge_liste
115 # des regles, on essaie de compenser comme suit :
116 # on ajoute les mots cles facteurs presents dont l'occurence n'est pas atteinte
117 for k in liste_mc_presents:
118 if k in liste:continue
119 objet = self.get_child(k,restreint = 'oui')
120 if isinstance(objet,MCFACT):
121 # un mot-clé facteur ne peut pas être répété plus de self.max fois
122 if objet.definition.max > 1:
124 elif isinstance(objet,MCList):
125 nb_occur_maxi = objet[0].definition.max
126 if len(objet) < nb_occur_maxi:
130 def liste_mc_presents(self):
132 Retourne la liste des noms des mots-clés fils de self présents construite
133 à partir de self.mc_liste
136 for v in self.mc_liste:
141 def get_index_child(self,nom_fils):
143 Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils
144 Permet de savoir à quelle position il faut ajouter un nouveau mot-clé
146 cata_ordonne = self.jdc.cata_ordonne_dico
147 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(self.get_genealogie(),cata_ordonne)
148 liste_noms_mc_presents = self.liste_mc_presents()
150 for nom in liste_noms_mc_ordonnee:
151 if nom == nom_fils:break
152 if nom not in liste_noms_mc_presents :continue
156 def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
158 Retourne liste_mc_a_ordonner ordonnée suivant l'ordre
159 donné par liste_noms_mc_ordonnee
162 # on transforme liste_a_ordonner en un dictionnaire (plus facile à consulter)
164 for mc in liste_mc_a_ordonner:
166 # on construit la liste des objets ordonnés
167 for nom_mc in liste_noms_mc_ordonnee:
168 if d_mc.has_key(nom_mc):
169 liste.append(d_mc.get(nom_mc))
173 def suppentite(self,objet) :
175 Supprime le fils 'objet' de self :
176 Retourne 1 si la suppression a pu être effectuée,
177 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
184 self.mc_liste.remove(objet)
185 CONNECTOR.Emit(self,"supp",objet)
186 objet.delete_mc_global()
187 objet.update_condition_bloc()
189 self.etape.modified()
196 def addentite(self,name,pos=None):
198 Ajoute le mot-cle name à la liste des mots-cles de
202 if type(name)==types.StringType :
203 # on est en mode création d'un motcle
204 if self.ispermis(name) == 0 : return 0
205 objet=self.definition.entites[name](val=None,nom=name,parent=self)
207 # dans ce cas on est en mode copie d'un motcle
209 # Appel de la methode qui fait le menage dans les references
210 # sur les concepts produits (verification que les concepts existent
211 # dans le contexte de la commande courante).
212 objet.verif_existence_sd()
214 # On verifie que l'ajout d'objet est autorise
215 if self.ispermis(objet) == 0:
216 self.jdc.appli.affiche_alerte("Erreur","L'objet %s ne peut être un fils de %s" %(objet.nom,
221 # On cherche s'il existe deja un mot cle de meme nom
222 old_obj = self.get_child(objet.nom,restreint = 'oui')
224 # on normalize l'objet
225 objet=objet.normalize()
226 # Le mot cle n'existe pas encore. On l'ajoute a la position
229 self.mc_liste.append(objet)
231 self.mc_liste.insert(pos,objet)
232 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
234 CONNECTOR.Emit(self,"add",objet)
235 objet.update_mc_global()
236 objet.update_condition_bloc()
240 # Le mot cle existe deja. Si le mot cle est repetable,
241 # on cree une liste d'objets. Dans le cas contraire,
242 # on emet un message d'erreur.
243 if not old_obj.isrepetable():
244 self.jdc.appli.affiche_alerte("Erreur","L'objet %s ne peut pas être répété" %objet.nom)
248 # une liste d'objets de même type existe déjà
249 old_obj.addentite(objet)
253 def ispermis(self,fils):
255 Retourne 1 si l'objet de nom nom_fils
256 est bien permis, cad peut bien être un fils de self,
259 if type(fils) == types.StringType :
260 # on veut juste savoir si self peut avoir un fils de nom 'fils'
261 if self.definition.entites.has_key(fils):
265 elif type(fils) == types.InstanceType:
266 # fils est un objet (commande,mcf,mclist)
267 # on est dans le cas d'une tentative de copie de l'objet
268 # on veut savoir si l'objet peut bien être un fils de self :
269 # la vérification du nom de suffit pas (plusieurs commandes
270 # ont le même mot-clé facteur AFFE ... et c'est l'utilisateur
271 # qui choisit le père d'où un risque d'erreur)
272 if not self.definition.entites.has_key(fils.nom):
275 if fils.parent.nom != self.nom : return 0
278 def update_concept(self,sd):
279 for child in self.mc_liste :
280 child.update_concept(sd)
282 def delete_concept(self,sd):
287 Mettre a jour les fils de l objet suite à la disparition du
289 Seuls les mots cles simples MCSIMP font un traitement autre que
290 de transmettre aux fils
292 for child in self.mc_liste :
293 child.delete_concept(sd)
295 def replace_concept(self,old_sd,sd):
298 - old_sd=concept remplace
299 - sd = nouveau concept
301 Mettre a jour les fils de l objet suite au remplacement du
304 for child in self.mc_liste :
305 child.replace_concept(old_sd,sd)
307 def get_liste_mc_inconnus(self):
309 Retourne la liste des mots-clés inconnus dans self
312 if self.reste_val != {}:
313 for k,v in self.reste_val.items() :
314 l_mc.append([self,k,v])
315 for child in self.mc_liste :
316 if child.isvalid() : continue
317 l_child = child.get_liste_mc_inconnus()
324 def deep_update_condition_bloc(self):
326 Parcourt l'arborescence des mcobject et realise l'update
327 des blocs conditionnels par appel de la methode update_condition_bloc
329 self._update_condition_bloc()
330 for mcobj in self.mc_liste:
331 if hasattr(mcobj,"deep_update_condition_bloc"):
332 mcobj.deep_update_condition_bloc()
334 def update_condition_bloc(self):
336 Realise l'update des blocs conditionnels fils de self
339 self._update_condition_bloc()
340 if self.parent:self.parent.update_condition_bloc()
342 def _update_condition_bloc(self):
344 Realise l'update des blocs conditionnels fils de self
346 dict = self.cree_dict_condition(self.mc_liste,condition=1)
347 for k,v in self.definition.entites.items():
348 if v.label != 'BLOC' :continue
349 globs= self.jdc and self.jdc.condition_context or {}
350 bloc=self.get_child(k,restreint = 'oui')
351 presence=v.verif_presence(dict,globs)
352 if presence and not bloc:
353 # le bloc doit être présent
354 # mais le bloc n'est pas présent et il doit être créé
355 #print "AJOUT BLOC",k
356 pos=self.get_index_child(k)
357 self.addentite(k,pos)
358 if not presence and bloc:
359 # le bloc devrait être absent
360 # le bloc est présent : il faut l'enlever
361 #print "SUPPRESSION BLOC",k,bloc
362 self.suppentite(bloc)
364 def verif_condition_bloc(self):
366 Evalue les conditions de tous les blocs fils possibles
367 (en fonction du catalogue donc de la définition) de self
368 et retourne deux listes :
369 - la première contient les noms des blocs à rajouter
370 - la seconde contient les noms des blocs à supprimer
374 dict = self.cree_dict_condition(self.mc_liste,condition=1)
375 for k,v in self.definition.entites.items():
377 globs= self.jdc and self.jdc.condition_context or {}
378 if v.verif_presence(dict,globs):
379 # le bloc doit être présent
380 if not self.get_child(k,restreint = 'oui'):
381 # le bloc n'est pas présent et il doit être créé
382 liste_ajouts.append(k)
384 # le bloc doit être absent
385 if self.get_child(k,restreint = 'oui'):
386 # le bloc est présent : il faut l'enlever
387 liste_retraits.append(k)
388 return liste_ajouts,liste_retraits
390 def verif_existence_sd(self):
392 Vérifie que les structures de données utilisées dans self existent bien dans le contexte
393 avant étape, sinon enlève la référence à ces concepts
395 for motcle in self.mc_liste :
396 motcle.verif_existence_sd()
398 def update_mc_global(self):
400 Met a jour les mots cles globaux enregistrés dans l'étape parente
401 et dans le jdc parent.
402 Un mot cle compose ne peut pas etre global. Il se contente de passer
403 la requete a ses fils.
405 for motcle in self.mc_liste :
406 motcle.update_mc_global()
408 def delete_mc_global(self):
409 for motcle in self.mc_liste :
410 motcle.delete_mc_global()
412 motcle.update_mc_global()
416 def init_modif_up(self):
417 Validation.V_MCCOMPO.MCCOMPO.init_modif_up(self)
418 CONNECTOR.Emit(self,"valid")