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()
195 def addentite(self,name,pos=None):
197 Ajoute le mot-cle name à la liste des mots-cles de
201 if type(name)==types.StringType :
202 # on est en mode création d'un motcle
203 if self.ispermis(name) == 0 : return 0
204 objet=self.definition.entites[name](val=None,nom=name,parent=self)
206 # dans ce cas on est en mode copie d'un motcle
208 # Appel de la methode qui fait le menage dans les references
209 # sur les concepts produits (verification que les concepts existent
210 # dans le contexte de la commande courante).
211 objet.verif_existence_sd()
213 # On verifie que l'ajout d'objet est autorise
214 if self.ispermis(objet) == 0:
215 self.jdc.send_message("L'objet %s ne peut être un fils de %s" %(objet.nom,
220 # On cherche s'il existe deja un mot cle de meme nom
221 old_obj = self.get_child(objet.nom,restreint = 'oui')
223 # on normalize l'objet
224 objet=objet.normalize()
225 # Le mot cle n'existe pas encore. On l'ajoute a la position
228 self.mc_liste.append(objet)
230 self.mc_liste.insert(pos,objet)
231 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
233 CONNECTOR.Emit(self,"add",objet)
234 objet.update_mc_global()
235 objet.update_condition_bloc()
239 # Le mot cle existe deja. Si le mot cle est repetable,
240 # on cree une liste d'objets. Dans le cas contraire,
241 # on emet un message d'erreur.
242 if not old_obj.isrepetable():
243 self.jdc.send_message("L'objet %s ne peut pas être répété" %objet.nom)
247 # une liste d'objets de même type existe déjà
248 old_obj.addentite(objet)
252 def ispermis(self,fils):
254 Retourne 1 si l'objet de nom nom_fils
255 est bien permis, cad peut bien être un fils de self,
258 if type(fils) == types.StringType :
259 # on veut juste savoir si self peut avoir un fils de nom 'fils'
260 if self.definition.entites.has_key(fils):
264 elif type(fils) == types.InstanceType:
265 # fils est un objet (commande,mcf,mclist)
266 # on est dans le cas d'une tentative de copie de l'objet
267 # on veut savoir si l'objet peut bien être un fils de self :
268 # la vérification du nom de suffit pas (plusieurs commandes
269 # ont le même mot-clé facteur AFFE ... et c'est l'utilisateur
270 # qui choisit le père d'où un risque d'erreur)
271 if not self.definition.entites.has_key(fils.nom):
274 if fils.parent.nom != self.nom : return 0
277 def update_concept(self,sd):
278 for child in self.mc_liste :
279 child.update_concept(sd)
281 def delete_concept(self,sd):
286 Mettre a jour les fils de l objet suite à la disparition du
288 Seuls les mots cles simples MCSIMP font un traitement autre que
289 de transmettre aux fils
291 for child in self.mc_liste :
292 child.delete_concept(sd)
294 def replace_concept(self,old_sd,sd):
297 - old_sd=concept remplace
298 - sd = nouveau concept
300 Mettre a jour les fils de l objet suite au remplacement du
303 for child in self.mc_liste :
304 child.replace_concept(old_sd,sd)
306 def get_liste_mc_inconnus(self):
308 Retourne la liste des mots-clés inconnus dans self
311 if self.reste_val != {}:
312 for k,v in self.reste_val.items() :
313 l_mc.append([self,k,v])
314 for child in self.mc_liste :
315 if child.isvalid() : continue
316 l_child = child.get_liste_mc_inconnus()
323 def deep_update_condition_bloc(self):
325 Parcourt l'arborescence des mcobject et realise l'update
326 des blocs conditionnels par appel de la methode update_condition_bloc
328 self._update_condition_bloc()
329 for mcobj in self.mc_liste:
330 if hasattr(mcobj,"deep_update_condition_bloc"):
331 mcobj.deep_update_condition_bloc()
333 def update_condition_bloc(self):
335 Realise l'update des blocs conditionnels fils de self
338 self._update_condition_bloc()
339 if self.parent:self.parent.update_condition_bloc()
341 def _update_condition_bloc(self):
343 Realise l'update des blocs conditionnels fils de self
345 dict = self.cree_dict_condition(self.mc_liste,condition=1)
346 for k,v in self.definition.entites.items():
347 if v.label != 'BLOC' :continue
348 globs= self.jdc and self.jdc.condition_context or {}
349 bloc=self.get_child(k,restreint = 'oui')
350 presence=v.verif_presence(dict,globs)
351 if presence and not bloc:
352 # le bloc doit être présent
353 # mais le bloc n'est pas présent et il doit être créé
354 #print "AJOUT BLOC",k
355 pos=self.get_index_child(k)
356 self.addentite(k,pos)
357 if not presence and bloc:
358 # le bloc devrait être absent
359 # le bloc est présent : il faut l'enlever
360 #print "SUPPRESSION BLOC",k,bloc
361 self.suppentite(bloc)
363 def verif_condition_bloc(self):
365 Evalue les conditions de tous les blocs fils possibles
366 (en fonction du catalogue donc de la définition) de self
367 et retourne deux listes :
368 - la première contient les noms des blocs à rajouter
369 - la seconde contient les noms des blocs à supprimer
373 dict = self.cree_dict_condition(self.mc_liste,condition=1)
374 for k,v in self.definition.entites.items():
376 globs= self.jdc and self.jdc.condition_context or {}
377 if v.verif_presence(dict,globs):
378 # le bloc doit être présent
379 if not self.get_child(k,restreint = 'oui'):
380 # le bloc n'est pas présent et il doit être créé
381 liste_ajouts.append(k)
383 # le bloc doit être absent
384 if self.get_child(k,restreint = 'oui'):
385 # le bloc est présent : il faut l'enlever
386 liste_retraits.append(k)
387 return liste_ajouts,liste_retraits
389 def verif_existence_sd(self):
391 Vérifie que les structures de données utilisées dans self existent bien dans le contexte
392 avant étape, sinon enlève la référence à ces concepts
394 for motcle in self.mc_liste :
395 motcle.verif_existence_sd()
397 def update_mc_global(self):
399 Met a jour les mots cles globaux enregistrés dans l'étape parente
400 et dans le jdc parent.
401 Un mot cle compose ne peut pas etre global. Il se contente de passer
402 la requete a ses fils.
404 for motcle in self.mc_liste :
405 motcle.update_mc_global()
407 def delete_mc_global(self):
408 for motcle in self.mc_liste :
409 motcle.delete_mc_global()
411 def init_modif_up(self):
412 Validation.V_MCCOMPO.MCCOMPO.init_modif_up(self)
413 CONNECTOR.Emit(self,"valid")