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