Salome HOME
*** empty log message ***
[tools/eficas.git] / Ihm / I_MCCOMPO.py
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.
9 #
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.
14 #
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.
18 #
19 #
20 # ======================================================================
21 """
22 """
23 import string,types,sys
24 from copy import copy
25 import traceback
26
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
31 import I_OBJECT
32 import Validation
33
34 import CONNECTOR
35
36 class MCCOMPO(I_OBJECT.OBJECT):
37   def getlabeltext(self):
38     """ 
39        Retourne le label de self 
40        utilisé pour l'affichage dans l'arbre
41     """
42     return self.nom
43
44   def get_liste_mc_ordonnee(self,liste,dico):
45     """
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 ...)
51     """
52     return self.filtre_liste_mc(self.get_liste_mc_ordonnee_brute(liste,dico))
53
54   def get_liste_mc_ordonnee_brute(self,liste,dico):
55     """
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 + ...
59     """
60     for arg in liste:
61         objet_cata = dico[arg]
62         dico=objet_cata.entites
63     return objet_cata.ordre_mc
64
65   def filtre_liste_mc(self,liste_brute):
66     """ 
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 
72        être répétés
73     """
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)
84     for k in liste_copy:
85       objet = self.get_child(k,restreint = 'oui')
86       if objet != None :
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é
90           liste.remove(k)
91         elif isinstance(objet,MCBLOC):
92           # un bloc conditionnel ne doit pas apparaître dans la liste de choix
93           liste.remove(k)
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:
97             liste.remove(k)
98         elif isinstance(objet,MCList):
99           try :
100             nb_occur_maxi = objet[0].definition.max
101             if len(objet) >= nb_occur_maxi:
102               liste.remove(k)
103           except:
104             pass
105         else :
106           #XXX CCAR : les MCNUPLET ne sont pas traités
107           if CONTEXT.debug : print '   ',k,' est un objet de type inconnu :',type(objet)
108       else :
109         # l'objet est absent : on enlève de la liste les blocs
110         if self.definition.entites[k].statut=='c' :
111           liste.remove(k)
112         if self.definition.entites[k].label=='BLOC':
113           liste.remove(k)
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:
123              liste.append(k)
124       elif isinstance(objet,MCList):
125           nb_occur_maxi = objet[0].definition.max
126           if len(objet) < nb_occur_maxi:
127               liste.append(k)
128     return liste
129
130   def liste_mc_presents(self):
131     """ 
132        Retourne la liste des noms des mots-clés fils de self présents construite
133        à partir de self.mc_liste 
134     """
135     l=[]
136     for v in self.mc_liste:
137       k=v.nom
138       l.append(k)
139     return l
140
141   def get_index_child(self,nom_fils):
142       """
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é
145       """
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()
149       index=0
150       for nom in liste_noms_mc_ordonnee:
151           if nom == nom_fils:break
152           if nom not in liste_noms_mc_presents :continue
153           index=index+1
154       return index
155           
156   def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
157     """
158         Retourne liste_mc_a_ordonner ordonnée suivant l'ordre 
159         donné par liste_noms_mc_ordonnee
160     """
161     liste = []
162     # on transforme liste_a_ordonner en un dictionnaire (plus facile à consulter)
163     d_mc = {}
164     for mc in liste_mc_a_ordonner:
165       d_mc[mc.nom]=mc
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))
170     # on la retourne
171     return liste
172
173   def suppentite(self,objet) :
174     """ 
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
178     """
179     if not objet in self.mc_liste:
180        # Impossible de supprimer objet. Il n'est pas dans mc_liste
181        return 0
182
183     self.init_modif()
184     self.mc_liste.remove(objet)
185     CONNECTOR.Emit(self,"supp",objet)
186     objet.delete_mc_global()
187     objet.update_condition_bloc()
188     objet.supprime()
189     self.fin_modif()
190     return 1
191
192   def isoblig(self):
193       return 0
194
195   def addentite(self,name,pos=None):
196       """ 
197           Ajoute le mot-cle name à la liste des mots-cles de
198           l'objet MCCOMPOSE
199       """
200       self.init_modif()
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)
205       else :
206         # dans ce cas on est en mode copie d'un motcle
207         objet = name
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()
212
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,
216                                                                         self.nom))
217         self.fin_modif()
218         return 0
219
220       # On cherche s'il existe deja un mot cle de meme nom
221       old_obj = self.get_child(objet.nom,restreint = 'oui')
222       if not old_obj :
223          # on normalize l'objet
224          objet=objet.normalize()
225          # Le mot cle n'existe pas encore. On l'ajoute a la position
226          # demandee (pos)
227          if pos == None :
228            self.mc_liste.append(objet)
229          else :
230            self.mc_liste.insert(pos,objet)
231          # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
232          objet.reparent(self)
233          CONNECTOR.Emit(self,"add",objet)
234          objet.update_mc_global()
235          objet.update_condition_bloc()
236          self.fin_modif()
237          return objet
238       else:
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)
244             self.fin_modif()
245             return 0
246          else:
247             # une liste d'objets de même type existe déjà
248             old_obj.addentite(objet)
249             self.fin_modif()
250             return old_obj
251
252   def ispermis(self,fils):
253     """ 
254         Retourne 1 si l'objet de nom nom_fils 
255         est bien permis, cad peut bien être un fils de self, 
256         Retourne 0 sinon 
257     """
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):
261         return 1
262       else :
263         return 0
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):
272         return 0
273       else:
274         if fils.parent.nom != self.nom : return 0
275       return 1
276
277   def update_concept(self,sd):
278     for child in self.mc_liste :
279         child.update_concept(sd)
280
281   def delete_concept(self,sd):
282     """ 
283         Inputs :
284            - sd=concept detruit
285         Fonction :
286         Mettre a jour les fils de l objet suite à la disparition du
287         concept sd
288         Seuls les mots cles simples MCSIMP font un traitement autre que 
289         de transmettre aux fils
290     """
291     for child in self.mc_liste :
292       child.delete_concept(sd)
293
294   def replace_concept(self,old_sd,sd):
295     """
296         Inputs :
297            - old_sd=concept remplace
298            - sd = nouveau concept
299         Fonction :
300         Mettre a jour les fils de l objet suite au remplacement  du
301         concept old_sd
302     """
303     for child in self.mc_liste :
304       child.replace_concept(old_sd,sd)
305
306   def get_liste_mc_inconnus(self):
307      """
308      Retourne la liste des mots-clés inconnus dans self
309      """
310      l_mc = []
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()
317         for mc in l_child:
318            l = [self]
319            l.extend(mc)
320            l_mc.append(l)
321      return l_mc
322
323   def deep_update_condition_bloc(self):
324      """
325         Parcourt l'arborescence des mcobject et realise l'update 
326         des blocs conditionnels par appel de la methode update_condition_bloc
327      """
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()
332
333   def update_condition_bloc(self):
334      """
335         Realise l'update des blocs conditionnels fils de self
336         et propage au parent
337      """
338      self._update_condition_bloc()
339      if self.parent:self.parent.update_condition_bloc()
340
341   def _update_condition_bloc(self):
342      """
343         Realise l'update des blocs conditionnels fils de self
344      """
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)
362
363   def verif_condition_bloc(self):
364     """ 
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
370     """
371     liste_ajouts = []
372     liste_retraits = []
373     dict = self.cree_dict_condition(self.mc_liste,condition=1)
374     for k,v in self.definition.entites.items():
375       if v.label=='BLOC' :
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)
382         else :
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
388
389   def verif_existence_sd(self):
390      """
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
393      """
394      for motcle in self.mc_liste :
395          motcle.verif_existence_sd()
396
397   def update_mc_global(self):
398      """
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.
403      """
404      for motcle in self.mc_liste :
405          motcle.update_mc_global()
406
407   def delete_mc_global(self):
408      for motcle in self.mc_liste :
409          motcle.delete_mc_global()
410      try :
411          motcle.update_mc_global()
412      except :
413         pass
414
415   def init_modif_up(self):
416     Validation.V_MCCOMPO.MCCOMPO.init_modif_up(self)
417     CONNECTOR.Emit(self,"valid")
418