Salome HOME
pour tenir compte des LASSD
[tools/eficas.git] / Ihm / I_MCCOMPO.py
index 0fcab2e6d2790916d91b58f206131a299de5cc6d..28bb21f1b8ef16260866641ae442c663eed744e4 100644 (file)
@@ -1,7 +1,28 @@
+# -*- coding: utf-8 -*-
+#            CONFIGURATION MANAGEMENT OF EDF VERSION
+# ======================================================================
+# COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
+# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
+# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
+# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
+# (AT YOUR OPTION) ANY LATER VERSION.
+#
+# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
+# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
+# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
+# GENERAL PUBLIC LICENSE FOR MORE DETAILS.
+#
+# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
+# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
+#    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
+#
+#
+# ======================================================================
 """
 """
 import string,types
 from copy import copy
+import traceback
 
 from Noyau.N_MCLIST import MCList
 from Noyau.N_MCSIMP import MCSIMP
@@ -9,21 +30,15 @@ from Noyau.N_MCFACT import MCFACT
 from Noyau.N_MCBLOC import MCBLOC
 import I_OBJECT
 
+import CONNECTOR
+
 class MCCOMPO(I_OBJECT.OBJECT):
   def getlabeltext(self):
     """ 
-       Retourne le label de self suivant qu'il s'agit d'un MCFACT, 
-       d'un MCBLOC ou d'un MCFACT appartenant à une MCList : 
-       utilisée pour l'affichage dans l'arbre
+       Retourne le label de self 
+       utilisé pour l'affichage dans l'arbre
     """
-    objet = self.parent.get_child(self.nom)
-    # objet peut-être self ou une MCList qui contient self ...
-    if isinstance(objet,MCList) :
-      index = objet.get_index(self)+1 # + 1 à cause de la numérotation qui commence à 0
-      label = self.nom +'_'+`index`+':'
-      return label
-    else:
-      return self.nom
+    return self.nom
 
   def get_liste_mc_ordonnee(self,liste,dico):
     """
@@ -43,8 +58,8 @@ class MCCOMPO(I_OBJECT.OBJECT):
     """
     for arg in liste:
         objet_cata = dico[arg]
-        dico=objet_cata.dico
-    return objet_cata.liste
+        dico=objet_cata.entites
+    return objet_cata.ordre_mc
 
   def filtre_liste_mc(self,liste_brute):
     """ 
@@ -95,6 +110,20 @@ class MCCOMPO(I_OBJECT.OBJECT):
           liste.remove(k)
         if self.definition.entites[k].label=='BLOC':
           liste.remove(k)
+    # Pour corriger les exces qui pourraient etre commis dans la methode purge_liste
+    # des regles, on essaie de compenser comme suit :
+    # on ajoute les mots cles facteurs presents dont l'occurence n'est pas atteinte
+    for k in liste_mc_presents:
+      if k in liste:continue
+      objet = self.get_child(k,restreint = 'oui')
+      if isinstance(objet,MCFACT):
+          # un mot-clé facteur ne peut pas être répété plus de self.max fois
+          if objet.definition.max > 1:
+             liste.append(k)
+      elif isinstance(objet,MCList):
+          nb_occur_maxi = objet[0].definition.max
+          if len(objet) < nb_occur_maxi:
+              liste.append(k)
     return liste
 
   def liste_mc_presents(self):
@@ -108,6 +137,21 @@ class MCCOMPO(I_OBJECT.OBJECT):
       l.append(k)
     return l
 
+  def get_index_child(self,nom_fils):
+      """
+        Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils
+        Permet de savoir à quelle position il faut ajouter un nouveau mot-clé
+      """
+      cata_ordonne = self.jdc.cata_ordonne_dico
+      liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(self.get_genealogie(),cata_ordonne)
+      liste_noms_mc_presents = self.liste_mc_presents()
+      index=0
+      for nom in liste_noms_mc_ordonnee:
+          if nom == nom_fils:break
+          if nom not in liste_noms_mc_presents :continue
+          index=index+1
+      return index
+          
   def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
     """
         Retourne liste_mc_a_ordonner ordonnée suivant l'ordre 
@@ -138,12 +182,19 @@ class MCCOMPO(I_OBJECT.OBJECT):
        return 0
 
     try :
+      self.mc_liste.remove(objet)
+      CONNECTOR.Emit(self,"supp",objet)
+
       if hasattr(objet.definition,'position'):
-          if objet.definition.position == 'global' :
+         if objet.definition.position == 'global' :
             self.delete_mc_global(objet)
-          elif objet.definition.position == 'global_jdc' :
+            self.etape.deep_update_condition_bloc()
+         elif objet.definition.position == 'global_jdc' :
             self.delete_mc_global_jdc(objet)
-      self.mc_liste.remove(objet)
+            self.jdc.deep_update_condition_bloc()
+      else:
+         self.update_condition_bloc()
+
       self.fin_modif()
       return 1
     except:
@@ -151,13 +202,14 @@ class MCCOMPO(I_OBJECT.OBJECT):
       return 0
 
   def isoblig(self):
-    return self.definition.statut=='o'
+      return 0
 
   def addentite(self,name,pos=None):
       """ 
           Ajoute le mot-cle name à la liste des mots-cles de
           l'objet MCCOMPOSE
       """
+      #print "I_MCCOMPO.addentite",name,pos
       self.init_modif()
       if type(name)==types.StringType :
         # on est en mode création d'un motcle 
@@ -171,61 +223,68 @@ class MCCOMPO(I_OBJECT.OBJECT):
       else :
         # dans ce cas on est en mode copie d'un motcle
         objet = name
+       # Appel de la methode qui fait le menage dans les references
+       # sur les concepts produits (verification que les concepts existent
+       # dans le contexte de la commande courante).
        objet.verif_existence_sd()
-      # si un objet de même nom est déjà présent dans la liste
-      # et si l'objet est répétable
-      # il faut créer une MCList et remplacer l'objet de la liste
-      # par la MCList
-      test1 = objet.isrepetable()
-      old_obj = self.get_child(objet.nom,restreint = 'oui')
-      test2 = self.ispermis(objet)
-      #print "test1,test2=",test1,test2
-      if test1 == 0 and old_obj :
-        self.jdc.send_message("L'objet %s ne peut pas être répété" %objet.nom)
-        self.fin_modif()
-        return 0
-      if test2 == 0:
-        self.jdc.send_message("L'objet %s ne peut être un fils de %s" %(objet.nom,self.nom))
+
+      # On verifie que l'ajout d'objet est autorise
+      if self.ispermis(objet) == 0:
+        self.jdc.send_message("L'objet %s ne peut être un fils de %s" %(objet.nom,
+                                                                       self.nom))
         self.fin_modif()
         return 0
-      if test1 :
-        if old_obj :
-          #if not isinstance(old_obj,MCList):
-          if not old_obj.isMCList():
-            # un objet de même nom existe déjà mais ce n'est pas une MCList
-            # Il faut en créer une 
-            # L'objet existant (old_obj) est certainement un MCFACT 
-            # qui pointe vers un constructeur
-            # de MCList : definition.liste_instance
-            #print "un objet de même type existe déjà"
-            index = self.mc_liste.index(old_obj)
-            #XXX remplacé par definition.list_instance : new_obj = MCList()
-            new_obj = old_obj.definition.list_instance()
-            new_obj.init(objet.nom,self)
-            new_obj.append(old_obj)
-            new_obj.append(objet)
-            # Il ne faut pas oublier de reaffecter le parent d'obj
-            objet.reparent(self)
-            self.mc_liste.remove(old_obj)
-            self.mc_liste.insert(index,new_obj)
-            self.fin_modif()
-            return new_obj
-          else :
-            # une liste d'objets de même type existe déjà
-            #print "une liste d'objets de même type existe déjà"
-            old_obj.append(objet)
-            # Il ne faut pas oublier de reaffecter le parent d'obj
-            objet.reparent(self)
+
+      # On cherche s'il existe deja un mot cle de meme nom
+      old_obj = self.get_child(objet.nom,restreint = 'oui')
+      #print "addentite",old_obj
+      #if old_obj:print "addentite",old_obj.isrepetable(),old_obj.isMCList(),old_obj.ajout_possible()
+      if not old_obj :
+         #print self.mc_liste,objet
+         # Le mot cle n'existe pas encore. On l'ajoute a la position
+        # demandee (pos)
+         if pos == None :
+           self.mc_liste.append(objet)
+         else :
+           self.mc_liste.insert(pos,objet)
+         #print self.mc_liste,objet
+         # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
+         objet.reparent(self)
+         CONNECTOR.Emit(self,"add",objet)
+         self.fin_modif()
+         return objet
+      else:
+         # Le mot cle existe deja. Si le mot cle est repetable,
+         # on cree une liste d'objets. Dans le cas contraire,
+         # on emet un message d'erreur.
+         if not old_obj.isrepetable():
+            self.jdc.send_message("L'objet %s ne peut pas être répété" %objet.nom)
             self.fin_modif()
-            return old_obj
-      if pos == None :
-        self.mc_liste.append(objet)
-      else :
-        self.mc_liste.insert(pos,objet)
-      # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
-      objet.reparent(self)
-      self.fin_modif()
-      return objet
+            return 0
+         else:
+            if not old_obj.isMCList():
+               # un objet de même nom existe déjà mais ce n'est pas une MCList
+               # Il faut en créer une 
+               # L'objet existant (old_obj) est certainement un MCFACT 
+               # qui pointe vers un constructeur
+               # de MCList : definition.liste_instance
+               index = self.mc_liste.index(old_obj)
+               new_obj = old_obj.definition.list_instance()
+               new_obj.init(objet.nom,self)
+               new_obj.append(old_obj)
+               new_obj.append(objet)
+               # Il ne faut pas oublier de reaffecter le parent d'obj
+               objet.reparent(self)
+               self.mc_liste.remove(old_obj)
+               CONNECTOR.Emit(self,"supp",old_obj)
+               self.mc_liste.insert(index,new_obj)
+               CONNECTOR.Emit(self,"add",new_obj)
+               self.fin_modif()
+               return new_obj
+            else :
+               # une liste d'objets de même type existe déjà
+               old_obj.addentite(objet)
+               return old_obj
 
   def ispermis(self,fils):
     """ 
@@ -252,30 +311,35 @@ class MCCOMPO(I_OBJECT.OBJECT):
         if fils.parent.nom != self.nom : return 0
       return 1
 
-  def liste_mc_presents(self):
-    """ 
-         Retourne la liste des noms des mots-clés fils de self présents 
-         construite à partir de self.mc_liste 
-    """
-    l=[]
-    for v in self.mc_liste:
-      k=v.nom
-      l.append(k)
-    return l
+  def update_concept(self,sd):
+    for child in self.mc_liste :
+        child.update_concept(sd)
 
   def delete_concept(self,sd):
     """ 
         Inputs :
-           sd=concept detruit
+           sd=concept detruit
         Fonction :
-           Mettre a jour les fils de l objet suite à la disparition du
-           concept sd
-           Seuls les mots cles simples MCSIMP font un traitement autre que 
-           de transmettre aux fils
+        Mettre a jour les fils de l objet suite à la disparition du
+        concept sd
+        Seuls les mots cles simples MCSIMP font un traitement autre que 
+        de transmettre aux fils
     """
     for child in self.mc_liste :
       child.delete_concept(sd)
 
+  def replace_concept(self,old_sd,sd):
+    """
+        Inputs :
+           - old_sd=concept remplace
+           - sd = nouveau concept
+        Fonction :
+        Mettre a jour les fils de l objet suite au remplacement  du
+        concept old_sd
+    """
+    for child in self.mc_liste :
+      child.replace_concept(old_sd,sd)
+
   def delete_mc_global(self,mc):
     """ 
         Supprime le mot-clé mc de la liste des mots-clés globaux de l'étape 
@@ -292,34 +356,6 @@ class MCCOMPO(I_OBJECT.OBJECT):
     nom = mc.nom
     del self.jdc.mc_globaux[nom]
 
-  def copy(self):
-    """ Retourne une copie de self """
-    objet = self.makeobjet()
-    # FR : attention !!! avec makeobjet, objet a le même parent que self
-    # ce qui n'est pas du tout bon dans le cas d'une copie !!!!!!!
-    # FR : peut-on passer par là autrement que dans le cas d'une copie ???
-    # FR --> je suppose que non
-    # XXX CCAR : le pb c'est qu'on vérifie ensuite quel parent avait l'objet
-    # Il me semble preferable de changer le parent a la fin quand la copie est acceptee
-    objet.valeur = copy(self.valeur)
-    objet.val = copy(self.val)
-    objet.mc_liste=[]
-    for obj in self.mc_liste:
-      new_obj = obj.copy()
-      new_obj.reparent(objet)
-      objet.mc_liste.append(new_obj)
-    return objet
-
-  def get_sd_utilisees(self):
-    """ 
-        Retourne la liste des concepts qui sont utilisés à l'intérieur de self
-        ( comme valorisation d'un MCS) 
-    """
-    l=[]
-    for child in self.mc_liste:
-      l.extend(child.get_sd_utilisees())
-    return l
-
   def get_liste_mc_inconnus(self):
      """
      Retourne la liste des mots-clés inconnus dans self
@@ -331,27 +367,61 @@ class MCCOMPO(I_OBJECT.OBJECT):
      for child in self.mc_liste :
         if child.isvalid() : continue
         l_child = child.get_liste_mc_inconnus()
-       if l_child :
+        for mc in l_child:
           l = [self]
-          l.extend(l_child)
+          l.extend(mc)
           l_mc.append(l)
      return l_mc
 
+  def deep_update_condition_bloc(self):
+     """
+        Parcourt l'arborescence des mcobject et realise l'update 
+        des blocs conditionnels par appel de la methode update_condition_bloc
+     """
+     #print "deep_update_condition_bloc",self
+     self.update_condition_bloc()
+     for mcobj in self.mc_liste:
+        if hasattr(mcobj,"deep_update_condition_bloc"):
+           mcobj.deep_update_condition_bloc()
+
+  def update_condition_bloc(self):
+     """
+        Realise l'update des blocs conditionnels fils de self
+     """
+     #print "update_condition_bloc",self
+     dict = self.cree_dict_condition(self.mc_liste,condition=1)
+     for k,v in self.definition.entites.items():
+        if v.label != 'BLOC' :continue
+        globs= self.jdc and self.jdc.condition_context or {}
+        bloc=self.get_child(k,restreint = 'oui')
+        presence=v.verif_presence(dict,globs)
+        if presence and not bloc:
+           # le bloc doit être présent
+           # mais le bloc n'est pas présent et il doit être créé
+           #print "AJOUT BLOC",k
+           pos=self.get_index_child(k)
+           self.addentite(k,pos)
+        if not presence and bloc:
+           # le bloc devrait être absent
+           # le bloc est présent : il faut l'enlever
+           #print "SUPPRESSION BLOC",k,bloc
+           self.suppentite(bloc)
+
   def verif_condition_bloc(self):
     """ 
         Evalue les conditions de tous les blocs fils possibles 
         (en fonction du catalogue donc de la définition) de self
         et retourne deux listes :
-        - la première contient les noms des blocs à rajouter
-        - la seconde contient les noms des blocs à supprimer
+          - la première contient les noms des blocs à rajouter
+          - la seconde contient les noms des blocs à supprimer
     """
     liste_ajouts = []
     liste_retraits = []
-    dict = self.cree_dict_valeurs(self.mc_liste)
+    dict = self.cree_dict_condition(self.mc_liste,condition=1)
     for k,v in self.definition.entites.items():
-      #dict = self.cree_dict_valeurs(self.mc_liste)
       if v.label=='BLOC' :
-        if v.verif_presence(dict) :
+        globs= self.jdc and self.jdc.condition_context or {}
+        if v.verif_presence(dict,globs):
           # le bloc doit être présent
           if not self.get_child(k,restreint = 'oui'):
             # le bloc n'est pas présent et il doit être créé
@@ -363,16 +433,6 @@ class MCCOMPO(I_OBJECT.OBJECT):
             liste_retraits.append(k)
     return liste_ajouts,liste_retraits
 
-  def reparent(self,parent):
-     """
-         Cette methode sert a reinitialiser la parente de l'objet
-     """
-     self.parent=parent
-     self.jdc=parent.get_jdc_root()
-     self.etape=parent.etape
-     for mocle in self.mc_liste:
-        mocle.reparent(self)
-
   def verif_existence_sd(self):
      """
         Vérifie que les structures de données utilisées dans self existent bien dans le contexte