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