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