Salome HOME
f9b03c339ca81e128781062d4bc9419340d702c7
[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.etape.modified()
190     self.fin_modif()
191     return 1
192
193   def isoblig(self):
194       return 0
195
196   def addentite(self,name,pos=None):
197       """ 
198           Ajoute le mot-cle name à la liste des mots-cles de
199           l'objet MCCOMPOSE
200       """
201       self.init_modif()
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)
206       else :
207         # dans ce cas on est en mode copie d'un motcle
208         objet = name
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()
213
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,
217                                                                         self.nom))
218         self.fin_modif()
219         return 0
220
221       # On cherche s'il existe deja un mot cle de meme nom
222       old_obj = self.get_child(objet.nom,restreint = 'oui')
223       if not old_obj :
224          # on normalize l'objet
225          objet=objet.normalize()
226          # Le mot cle n'existe pas encore. On l'ajoute a la position
227          # demandee (pos)
228          if pos == None :
229            self.mc_liste.append(objet)
230          else :
231            self.mc_liste.insert(pos,objet)
232          # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
233          objet.reparent(self)
234          CONNECTOR.Emit(self,"add",objet)
235          objet.update_mc_global()
236          objet.update_condition_bloc()
237          self.fin_modif()
238          return objet
239       else:
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)
245             self.fin_modif()
246             return 0
247          else:
248             # une liste d'objets de même type existe déjà
249             old_obj.addentite(objet)
250             self.fin_modif()
251             return old_obj
252
253   def ispermis(self,fils):
254     """ 
255         Retourne 1 si l'objet de nom nom_fils 
256         est bien permis, cad peut bien être un fils de self, 
257         Retourne 0 sinon 
258     """
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):
262         return 1
263       else :
264         return 0
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):
273         return 0
274       else:
275         if fils.parent.nom != self.nom : return 0
276       return 1
277
278   def update_concept(self,sd):
279     for child in self.mc_liste :
280         child.update_concept(sd)
281
282   def delete_concept(self,sd):
283     """ 
284         Inputs :
285            - sd=concept detruit
286         Fonction :
287         Mettre a jour les fils de l objet suite à la disparition du
288         concept sd
289         Seuls les mots cles simples MCSIMP font un traitement autre que 
290         de transmettre aux fils
291     """
292     for child in self.mc_liste :
293       child.delete_concept(sd)
294
295   def replace_concept(self,old_sd,sd):
296     """
297         Inputs :
298            - old_sd=concept remplace
299            - sd = nouveau concept
300         Fonction :
301         Mettre a jour les fils de l objet suite au remplacement  du
302         concept old_sd
303     """
304     for child in self.mc_liste :
305       child.replace_concept(old_sd,sd)
306
307   def get_liste_mc_inconnus(self):
308      """
309      Retourne la liste des mots-clés inconnus dans self
310      """
311      l_mc = []
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()
318         for mc in l_child:
319            l = [self]
320            l.extend(mc)
321            l_mc.append(l)
322      return l_mc
323
324   def deep_update_condition_bloc(self):
325      """
326         Parcourt l'arborescence des mcobject et realise l'update 
327         des blocs conditionnels par appel de la methode update_condition_bloc
328      """
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()
333
334   def update_condition_bloc(self):
335      """
336         Realise l'update des blocs conditionnels fils de self
337         et propage au parent
338      """
339      self._update_condition_bloc()
340      if self.parent:self.parent.update_condition_bloc()
341
342   def _update_condition_bloc(self):
343      """
344         Realise l'update des blocs conditionnels fils de self
345      """
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)
363
364   def verif_condition_bloc(self):
365     """ 
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
371     """
372     liste_ajouts = []
373     liste_retraits = []
374     dict = self.cree_dict_condition(self.mc_liste,condition=1)
375     for k,v in self.definition.entites.items():
376       if v.label=='BLOC' :
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)
383         else :
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
389
390   def verif_existence_sd(self):
391      """
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
394      """
395      for motcle in self.mc_liste :
396          motcle.verif_existence_sd()
397
398   def update_mc_global(self):
399      """
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.
404      """
405      for motcle in self.mc_liste :
406          motcle.update_mc_global()
407
408   def delete_mc_global(self):
409      for motcle in self.mc_liste :
410          motcle.delete_mc_global()
411      try :
412          motcle.update_mc_global()
413      except :
414         pass
415
416   def init_modif_up(self):
417     Validation.V_MCCOMPO.MCCOMPO.init_modif_up(self)
418     CONNECTOR.Emit(self,"valid")
419