Salome HOME
modif commentaire version
[tools/eficas.git] / Ihm / I_MCCOMPO.py
1 #            CONFIGURATION MANAGEMENT OF EDF VERSION
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
8 #
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
13 #
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
17 #
18 #
19 # ======================================================================
20 """
21 """
22 import string,types
23 from copy import copy
24
25 from Noyau.N_MCLIST import MCList
26 from Noyau.N_MCSIMP import MCSIMP
27 from Noyau.N_MCFACT import MCFACT
28 from Noyau.N_MCBLOC import MCBLOC
29 import I_OBJECT
30
31 class MCCOMPO(I_OBJECT.OBJECT):
32   def getlabeltext(self):
33     """ 
34        Retourne le label de self suivant qu'il s'agit d'un MCFACT, 
35        d'un MCBLOC ou d'un MCFACT appartenant à une MCList : 
36        utilisée pour l'affichage dans l'arbre
37     """
38     objet = self.parent.get_child(self.nom)
39     # objet peut-être self ou une MCList qui contient self ...
40     if isinstance(objet,MCList) :
41       index = objet.get_index(self)+1 # + 1 à cause de la numérotation qui commence à 0
42       label = self.nom +'_'+`index`+':'
43       return label
44     else:
45       return self.nom
46
47   def get_liste_mc_ordonnee(self,liste,dico):
48     """
49        Retourne la liste ordonnée (suivant le catalogue) des mots-clés
50        d'une entité composée dont le chemin complet est donné sous forme
51        d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
52        il faut encore réarranger cette liste (certains mots-clés déjà
53        présents ne doivent plus être proposés, règles ...)
54     """
55     return self.filtre_liste_mc(self.get_liste_mc_ordonnee_brute(liste,dico))
56
57   def get_liste_mc_ordonnee_brute(self,liste,dico):
58     """
59        Retourne la liste ordonnée (suivant le catalogue) BRUTE des mots-clés
60        d'une entité composée dont le chemin complet est donné sous forme
61        d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
62     """
63     for arg in liste:
64         objet_cata = dico[arg]
65         dico=objet_cata.entites
66     return objet_cata.ordre_mc
67
68   def filtre_liste_mc(self,liste_brute):
69     """ 
70        Cette méthode est appelée par EFICAS afin de présenter à 
71        l'utilisateur la liste des enfants possibles de self actualisée 
72        en fonction du contexte de self. En clair, sont supprimés de la
73        liste des possibles (fournie par la définition), les mots-clés
74        exclus par les règles de self et les mots-clés ne pouvant plus 
75        être répétés
76     """
77     liste = copy(liste_brute)
78     liste_mc_presents = self.liste_mc_presents()
79     # on enlève les mots-clés non permis par les règles
80     for regle in self.definition.regles:
81        # la méthode purge_liste est à développer pour chaque règle qui
82        # influe sur la liste de choix à proposer à l'utilisateur
83        # --> EXCLUS,UN_PARMI,PRESENT_ABSENT
84        liste = regle.purge_liste(liste,liste_mc_presents)
85     # on enlève les mots-clés dont l'occurrence est déjà atteinte
86     liste_copy = copy(liste)
87     for k in liste_copy:
88       objet = self.get_child(k,restreint = 'oui')
89       if objet != None :
90         # l'objet est déjà présent : il faut distinguer plusieurs cas
91         if isinstance(objet,MCSIMP):
92           # un mot-clé simple ne peut pas être répété
93           liste.remove(k)
94         elif isinstance(objet,MCBLOC):
95           # un bloc conditionnel ne doit pas apparaître dans la liste de choix
96           liste.remove(k)
97         elif isinstance(objet,MCFACT):
98           # un mot-clé facteur ne peut pas être répété plus de self.max fois
99           if objet.definition.max == 1:
100             liste.remove(k)
101         elif isinstance(objet,MCList):
102           try :
103             nb_occur_maxi = objet[0].definition.max
104             if len(objet) >= nb_occur_maxi:
105               liste.remove(k)
106           except:
107             pass
108         else :
109           #XXX CCAR : les MCNUPLET ne sont pas traités
110           if CONTEXT.debug : print '   ',k,' est un objet de type inconnu :',type(objet)
111       else :
112         # l'objet est absent : on enlève de la liste les blocs
113         if self.definition.entites[k].statut=='c' :
114           liste.remove(k)
115         if self.definition.entites[k].label=='BLOC':
116           liste.remove(k)
117     # Pour corriger les exces qui pourraient etre commis dans la methode purge_liste
118     # des regles, on essaie de compenser comme suit :
119     # on ajoute les mots cles facteurs presents dont l'occurence n'est pas atteinte
120     for k in liste_mc_presents:
121       if k in liste:continue
122       objet = self.get_child(k,restreint = 'oui')
123       if isinstance(objet,MCFACT):
124           # un mot-clé facteur ne peut pas être répété plus de self.max fois
125           if objet.definition.max > 1:
126              liste.append(k)
127       elif isinstance(objet,MCList):
128           nb_occur_maxi = objet[0].definition.max
129           if len(objet) < nb_occur_maxi:
130               liste.append(k)
131     return liste
132
133   def liste_mc_presents(self):
134     """ 
135        Retourne la liste des noms des mots-clés fils de self présents construite
136        à partir de self.mc_liste 
137     """
138     l=[]
139     for v in self.mc_liste:
140       k=v.nom
141       l.append(k)
142     return l
143
144   def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
145     """
146         Retourne liste_mc_a_ordonner ordonnée suivant l'ordre 
147         donné par liste_noms_mc_ordonnee
148     """
149     liste = []
150     # on transforme liste_a_ordonner en un dictionnaire (plus facile à consulter)
151     d_mc = {}
152     for mc in liste_mc_a_ordonner:
153       d_mc[mc.nom]=mc
154     # on construit la liste des objets ordonnés
155     for nom_mc in liste_noms_mc_ordonnee:
156       if d_mc.has_key(nom_mc):
157         liste.append(d_mc.get(nom_mc))
158     # on la retourne
159     return liste
160
161   def suppentite(self,objet) :
162     """ 
163         Supprime le fils 'objet' de self : 
164         Retourne 1 si la suppression a pu être effectuée,
165         Retourne 0 dans le cas contraire
166     """
167     self.init_modif()
168     if not objet in self.mc_liste:
169        # Impossible de supprimer objet. Il n'est pas dans mc_liste
170        self.fin_modif()
171        return 0
172
173     try :
174       if hasattr(objet.definition,'position'):
175           if objet.definition.position == 'global' :
176             self.delete_mc_global(objet)
177           elif objet.definition.position == 'global_jdc' :
178             self.delete_mc_global_jdc(objet)
179       self.mc_liste.remove(objet)
180       self.fin_modif()
181       return 1
182     except:
183       self.fin_modif()
184       return 0
185
186   def isoblig(self):
187     return self.definition.statut=='o'
188
189   def addentite(self,name,pos=None):
190       """ 
191           Ajoute le mot-cle name à la liste des mots-cles de
192           l'objet MCCOMPOSE
193       """
194       self.init_modif()
195       if type(name)==types.StringType :
196         # on est en mode création d'un motcle 
197         if self.ispermis(name) == 0 : return 0
198         objet=self.definition.entites[name](val=None,nom=name,parent=self)
199         if hasattr(objet.definition,'position'):
200           if objet.definition.position == 'global' :
201             self.append_mc_global(objet)
202           elif objet.definition.position == 'global_jdc' :
203             self.append_mc_global_jdc(objet)
204       else :
205         # dans ce cas on est en mode copie d'un motcle
206         objet = name
207         objet.verif_existence_sd()
208       # si un objet de même nom est déjà présent dans la liste
209       # et si l'objet est répétable
210       # il faut créer une MCList et remplacer l'objet de la liste
211       # par la MCList
212       test1 = objet.isrepetable()
213       old_obj = self.get_child(objet.nom,restreint = 'oui')
214       test2 = self.ispermis(objet)
215       #print "test1,test2=",test1,test2
216       if test1 == 0 and old_obj :
217         self.jdc.send_message("L'objet %s ne peut pas être répété" %objet.nom)
218         self.fin_modif()
219         return 0
220       if test2 == 0:
221         self.jdc.send_message("L'objet %s ne peut être un fils de %s" %(objet.nom,self.nom))
222         self.fin_modif()
223         return 0
224       if test1 :
225         if old_obj :
226           #if not isinstance(old_obj,MCList):
227           if not old_obj.isMCList():
228             # un objet de même nom existe déjà mais ce n'est pas une MCList
229             # Il faut en créer une 
230             # L'objet existant (old_obj) est certainement un MCFACT 
231             # qui pointe vers un constructeur
232             # de MCList : definition.liste_instance
233             #print "un objet de même type existe déjà"
234             index = self.mc_liste.index(old_obj)
235             #XXX remplacé par definition.list_instance : new_obj = MCList()
236             new_obj = old_obj.definition.list_instance()
237             new_obj.init(objet.nom,self)
238             new_obj.append(old_obj)
239             new_obj.append(objet)
240             # Il ne faut pas oublier de reaffecter le parent d'obj
241             objet.reparent(self)
242             self.mc_liste.remove(old_obj)
243             self.mc_liste.insert(index,new_obj)
244             self.fin_modif()
245             return new_obj
246           else :
247             # une liste d'objets de même type existe déjà
248             #print "une liste d'objets de même type existe déjà"
249             old_obj.append(objet)
250             # Il ne faut pas oublier de reaffecter le parent d'obj
251             objet.reparent(self)
252             self.fin_modif()
253             return old_obj
254       if pos == None :
255         self.mc_liste.append(objet)
256       else :
257         self.mc_liste.insert(pos,objet)
258       # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
259       objet.reparent(self)
260       self.fin_modif()
261       return objet
262
263   def ispermis(self,fils):
264     """ 
265         Retourne 1 si l'objet de nom nom_fils 
266         est bien permis, cad peut bien être un fils de self, 
267         Retourne 0 sinon 
268     """
269     if type(fils) == types.StringType :
270       # on veut juste savoir si self peut avoir un fils de nom 'fils'
271       if self.definition.entites.has_key(fils):
272         return 1
273       else :
274         return 0
275     elif type(fils) == types.InstanceType:
276       # fils est un objet (commande,mcf,mclist)
277       # on est dans le cas d'une tentative de copie de l'objet
278       # on veut savoir si l'objet peut bien être un fils de self :
279       # la vérification du nom de suffit pas (plusieurs commandes
280       # ont le même mot-clé facteur AFFE ... et c'est l'utilisateur
281       # qui choisit le père d'où un risque d'erreur)
282       if not self.definition.entites.has_key(fils.nom):
283         return 0
284       else:
285         if fils.parent.nom != self.nom : return 0
286       return 1
287
288   def liste_mc_presents(self):
289     """ 
290          Retourne la liste des noms des mots-clés fils de self présents 
291          construite à partir de self.mc_liste 
292     """
293     l=[]
294     for v in self.mc_liste:
295       k=v.nom
296       l.append(k)
297     return l
298
299   def delete_concept(self,sd):
300     """ 
301         Inputs :
302            sd=concept detruit
303         Fonction :
304            Mettre a jour les fils de l objet suite à la disparition du
305            concept sd
306            Seuls les mots cles simples MCSIMP font un traitement autre que 
307            de transmettre aux fils
308     """
309     for child in self.mc_liste :
310       child.delete_concept(sd)
311
312   def replace_concept(self,old_sd,sd):
313     """
314         Inputs :
315            old_sd=concept remplace
316            sd = nouveau concept
317         Fonction :
318            Mettre a jour les fils de l objet suite au remplacement  du
319            concept old_sd
320     """
321     for child in self.mc_liste :
322       child.replace_concept(old_sd,sd)
323
324   def delete_mc_global(self,mc):
325     """ 
326         Supprime le mot-clé mc de la liste des mots-clés globaux de l'étape 
327     """
328     etape = self.get_etape()
329     if etape :
330       nom = mc.nom
331       del etape.mc_globaux[nom]
332
333   def delete_mc_global_jdc(self,mc):
334     """ 
335         Supprime le mot-clé mc de la liste des mots-clés globaux du jdc 
336     """
337     nom = mc.nom
338     del self.jdc.mc_globaux[nom]
339
340   def copy(self):
341     """ Retourne une copie de self """
342     objet = self.makeobjet()
343     # FR : attention !!! avec makeobjet, objet a le même parent que self
344     # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
345     # FR : peut-on passer par là autrement que dans le cas d'une copie ???
346     # FR --> je suppose que non
347     # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
348     # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
349     objet.valeur = copy(self.valeur)
350     objet.val = copy(self.val)
351     objet.mc_liste=[]
352     for obj in self.mc_liste:
353       new_obj = obj.copy()
354       new_obj.reparent(objet)
355       objet.mc_liste.append(new_obj)
356     return objet
357
358   def get_sd_utilisees(self):
359     """ 
360         Retourne la liste des concepts qui sont utilisés à l'intérieur de self
361         ( comme valorisation d'un MCS) 
362     """
363     l=[]
364     for child in self.mc_liste:
365       l.extend(child.get_sd_utilisees())
366     return l
367
368   def get_liste_mc_inconnus(self):
369      """
370      Retourne la liste des mots-clés inconnus dans self
371      """
372      l_mc = []
373      if self.reste_val != {}:
374         for k,v in self.reste_val.items() :
375             l_mc.append([self,k,v])
376      for child in self.mc_liste :
377         if child.isvalid() : continue
378         l_child = child.get_liste_mc_inconnus()
379         for mc in l_child:
380            l = [self]
381            l.extend(mc)
382            l_mc.append(l)
383      return l_mc
384
385   def verif_condition_bloc(self):
386     """ 
387         Evalue les conditions de tous les blocs fils possibles 
388         (en fonction du catalogue donc de la définition) de self
389         et retourne deux listes :
390         - la première contient les noms des blocs à rajouter
391         - la seconde contient les noms des blocs à supprimer
392     """
393     liste_ajouts = []
394     liste_retraits = []
395     dict = self.cree_dict_valeurs(self.mc_liste)
396     for k,v in self.definition.entites.items():
397       if v.label=='BLOC' :
398         globs= self.jdc and self.jdc.condition_context or {}
399         if v.verif_presence(dict,globs):
400           # le bloc doit être présent
401           if not self.get_child(k,restreint = 'oui'):
402             # le bloc n'est pas présent et il doit être créé
403             liste_ajouts.append(k)
404         else :
405           # le bloc doit être absent
406           if self.get_child(k,restreint = 'oui'):
407             # le bloc est présent : il faut l'enlever
408             liste_retraits.append(k)
409     return liste_ajouts,liste_retraits
410
411   def reparent(self,parent):
412      """
413          Cette methode sert a reinitialiser la parente de l'objet
414      """
415      self.parent=parent
416      self.jdc=parent.get_jdc_root()
417      self.etape=parent.etape
418      for mocle in self.mc_liste:
419         mocle.reparent(self)
420
421   def verif_existence_sd(self):
422      """
423         Vérifie que les structures de données utilisées dans self existent bien dans le contexte
424         avant étape, sinon enlève la référence à ces concepts
425      """
426      for motcle in self.mc_liste :
427          motcle.verif_existence_sd()