Salome HOME
premiere version
[tools/eficas.git] / Ihm / I_ETAPE.py
index 33a517b78a9fd85dc5d35bbdeb96b75f72f9b215..8b0bf7af4d7a435d8a37f14baae4ddfadb267148 100644 (file)
@@ -1,37 +1,47 @@
-#            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.
+# -*- coding: utf-8 -*-
+# Copyright (C) 2007-2013   EDF R&D
 #
 #
-# 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.
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
 #
 #
-# 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.
+# This library 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
+# Lesser General Public License for more details.
 #
 #
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 #
 #
-# ======================================================================
 """
 """
 # Modules Python
 """
 """
 # Modules Python
+import sys,re
 import string,types
 from copy import copy
 
 import string,types
 from copy import copy
 
-# import rajoutés suite à l'ajout de Build_sd --> à résorber
+from Extensions.i18n import tr
+from Extensions.eficas_exception import EficasException
+
+# Objet re pour controler les identificateurs Python
+concept_re=re.compile(r'[a-zA-Z_]\w*$')
+
+# import rajoute suite a l'ajout de Build_sd --> a resorber
 import traceback
 import Noyau
 from Noyau import N_Exception
 from Noyau.N_Exception import AsException
 import traceback
 import Noyau
 from Noyau import N_Exception
 from Noyau.N_Exception import AsException
-# fin import à résorber
+import Validation
+# fin import a resorber
 
 # Modules EFICAS
 import I_MCCOMPO
 
 # Modules EFICAS
 import I_MCCOMPO
+import CONNECTOR
+from Extensions import commande_comm
 
 class ETAPE(I_MCCOMPO.MCCOMPO):
 
 
 class ETAPE(I_MCCOMPO.MCCOMPO):
 
@@ -39,13 +49,16 @@ class ETAPE(I_MCCOMPO.MCCOMPO):
       return self.nom
 
    def get_sdname(self):
       return self.nom
 
    def get_sdname(self):
-      if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
+      #print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
+      if CONTEXT.debug : 
+          print "SDNAME ",  self.reuse,  self.sd,  self.sd.get_name()
+      sdname=''
       if self.reuse != None:
         sdname= self.reuse.get_name()
       else:
       if self.reuse != None:
         sdname= self.reuse.get_name()
       else:
-        sdname=self.sd.get_name()
+        if self.sd:sdname=self.sd.get_name()
       if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1:
       if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1:
-        # dans le cas où la SD est 'sansnom' ou 'SD_' on retourne la chaîne vide
+        # dans le cas ou la SD est 'sansnom' ou 'SD_' on retourne la chaine vide
         return ''
       return sdname
 
         return ''
       return sdname
 
@@ -57,129 +70,147 @@ class ETAPE(I_MCCOMPO.MCCOMPO):
 
    def init_modif(self):
       """
 
    def init_modif(self):
       """
-         Met l'état de l'étape à : modifié
+         Met l'etat de l'etape a : modifie
          Propage la modification au parent
          Propage la modification au parent
-         Si la fonction op_init existe, l'active
       """
       """
-      # Une action
-      # doit etre realisée apres init_modif et la validite reevaluée
-      # apres cette action. L'état modified de tous les objets doit etre
-      # preservé.
+      # init_modif doit etre appele avant de realiser une modification
+      # La validite devra etre recalculee apres cette modification
+      # mais dans l'appel a fin_modif pour preserver l'etat modified
+      # de tous les objets entre temps
+      #print "init_modif",self,self.parent
       self.state = 'modified'
       if self.parent:
         self.parent.init_modif()
 
    def fin_modif(self):
       """
       self.state = 'modified'
       if self.parent:
         self.parent.init_modif()
 
    def fin_modif(self):
       """
-          Méthode appelée une fois qu'une modification a été faite afin de 
-          déclencher d'éventuels traitements post-modification
+          Methode appelee une fois qu'une modification a ete faite afin de 
+          declencher d'eventuels traitements post-modification
           ex : INCLUDE et POURSUITE
           ex : INCLUDE et POURSUITE
+          Ne pas mettre de traitement qui risque d'induire des recursions (soit a peu pres rien)
       """
       """
-      if self.isvalid() :
-         if type(self.definition.op_init) == types.FunctionType :
-            # XXX Normalement en mode editeur g_context ne peut pas etre utilisé
-            apply(self.definition.op_init,(self,self.parent.g_context))   
-      self.state = 'modified'
-    
+      CONNECTOR.Emit(self,"valid")
+      if self.parent:
+        self.parent.fin_modif()
+
    def nomme_sd(self,nom) :
       """
    def nomme_sd(self,nom) :
       """
-          Cette méthode a pour fonction de donner un nom (nom) au concept 
-          produit par l'étape (self).
-          - si le concept n'existe pas, on essaye de le créer (à condition que l'étape soit valide ET non réentrante)
-          - si il existe déjà, on le renomme et on répercute les changements dans les autres étapes    
+          Cette methode a pour fonction de donner un nom (nom) au concept 
+          produit par l'etape (self).
+            - si le concept n'existe pas, on essaye de le creer a condition que l'etape soit valide ET non reentrante)
+            - si il existe dea, on le renomme et on repercute les changements dans les autres etapes    
           Les valeurs de retour sont :
           Les valeurs de retour sont :
-           0 si le nommage n'a pas pu etre mené à son terme,
-           1 dans le cas contraire
+            - 0 si le nommage n'a pas pu etre menea son terme,
+            - 1 dans le cas contraire
       """
       """
-      if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
-        return 0,"Nom de concept trop long (maxi 8 caractères)"
+      # Le nom d'un concept doit etre un identificateur Python (toujours vrai ?)
+      if not concept_re.match(nom):
+         return 0, tr("Un nom de concept doit etre un identificateur Python")
+
+      #if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
+      #  return 0, tr("Nom de concept trop long (maxi 8 caracteres)")
+
       self.init_modif()
       self.init_modif()
-      if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
       #
       #
-      # Cas particulier des opérateurs obligatoirement réentrants
+      # On verifie d'abord si les mots cles sont valides
+      #
+      if not self.isvalid(sd='non') : return 0,"Nommage du concept refuse : l'operateur n'est pas valide"
+      #
+      # Cas particulier des operateurs obligatoirement reentrants
       #
       if self.definition.reentrant == 'o':
       #
       if self.definition.reentrant == 'o':
-        # FR : appel à get_sdprod incorrect : il faut appeler get_sd_avant_etape
-        #self.sd = self.reuse = self.jdc.get_sdprod(nom)
-       self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
+        self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
         if self.sd != None :
           self.sdnom=self.sd.nom
         if self.sd != None :
           self.sdnom=self.sd.nom
-          return 1,"Concept existant"
+          self.fin_modif()
+          return 1, tr("Concept existant")
         else:
         else:
-          return 0,"Opérateur réentrant mais concept non existant"
+          return 0, tr("Operateur reentrant mais concept non existant")
       #
       #
-      # Cas particulier des opérateurs facultativement réentrants
+      # Cas particulier des operateurs facultativement reentrants
       #
       old_reuse=None
       if self.definition.reentrant == 'f' :
         sd = self.jdc.get_sd_avant_etape(nom,self)
         if sd != None :
       #
       old_reuse=None
       if self.definition.reentrant == 'f' :
         sd = self.jdc.get_sd_avant_etape(nom,self)
         if sd != None :
-         # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!!
-         if isinstance(sd,self.get_type_produit()) :
+          if isinstance(sd,self.get_type_produit()) :
              self.sd = self.reuse = sd
              self.sdnom = sd.nom
              self.sd = self.reuse = sd
              self.sdnom = sd.nom
-             return 1,"Opérateur facultativement réentrant et concept existant trouvé"
-         else:
-            return 0,"Concept déjà existant et de mauvais type"
+             self.fin_modif()
+             return 1, tr("Operateur reentrant et concept existant trouve")
+          else:
+             return 0, tr("Concept deja existant et de mauvais type")
         else :
           # il faut enlever le lien vers une SD existante car si on passe ici
         else :
           # il faut enlever le lien vers une SD existante car si on passe ici
-         # cela signifie que l'opérateur n'est pas utilisé en mode réentrant.
-         # Si on ne fait pas cela, on risque de modifier une SD produite par un autre opérateur
-         if self.reuse :
+          # cela signifie que l'operateur n'est pas utilise en mode reentrant.
+          # Si on ne fait pas cela, on risque de modifier une SD produite par un autre operateur
+          if self.reuse :
              old_reuse=self.reuse
              old_reuse=self.reuse
-            self.sd = self.reuse = self.sdnom = None
+             self.sd = self.reuse = self.sdnom = None
       #
       #
-      # On est dans le cas ou l'opérateur n'est pas réentrant ou est facultativement reentrant
-      # mais est utilisé en mode non réentrant
+      # On est dans le cas ou l'operateur n'est pas reentrant ou est facultativement reentrant
+      # mais est utilise en mode non reentrant
       #
       if self.sd == None :
       #
       if self.sd == None :
+          #Pas de concept produit preexistant
           if self.parent.get_sd_autour_etape(nom,self):
             # Un concept de ce nom existe dans le voisinage de l'etape courante
           if self.parent.get_sd_autour_etape(nom,self):
             # Un concept de ce nom existe dans le voisinage de l'etape courante
-            # On force self.valid a 0 car l appel a isvalid precedent l a mis a 1
-            # mais ceci indique seulement une validité partielle
-            # isvalid ne devrait peut etre pas mettre l attribut valid à 1 si sd == 'non'
-            self.valid=0
             # On retablit l'ancien concept reentrant s'il existait
             if old_reuse:
                self.sd=self.reuse=old_reuse
                self.sdnom=old_reuse.nom
             # On retablit l'ancien concept reentrant s'il existait
             if old_reuse:
                self.sd=self.reuse=old_reuse
                self.sdnom=old_reuse.nom
-            return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
+            return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
           else:
             # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
           else:
             # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
-            # On peut donc créer le concept retourné.
-            # Il est créé sans nom mais enregistré dans la liste des concepts existants
-            self.get_sd_prod()
-            # Il suffit de changer son attribut nom pour le nommer
-            self.sd.nom = nom
-            self.sdnom=nom
-            return 1,"Nommage du concept effectué"
+            # On peut donc creer le concept retourne
+            # Il est cree sans nom mais enregistre dans la liste des concepts existants
+            try:
+               self.get_sd_prod()
+               # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
+               self.sd.nom = nom
+               self.sdnom=nom
+               self.parent.update_concept_after_etape(self,self.sd)
+               self.fin_modif()
+               return 1, tr("Nommage du concept effectue")
+            except:
+               return 0, tr("Nommage impossible %s", str(sys.exc_info()[1]))
       else :
       else :
+          #Un concept produit preexiste
           old_nom=self.sd.nom
           if string.find(old_nom,'sansnom') :
           old_nom=self.sd.nom
           if string.find(old_nom,'sansnom') :
-            # Dans le cas où old_nom == sansnom, isvalid retourne 0 alors que ...
-           # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'étape est valide
-           # on peut donc le nommer sans test préalable
-           self.sd.nom=nom
-            self.sdnom=nom
-            return 1,"Nommage du concept effectué"
+            # Dans le cas ou old_nom == sansnom, isvalid retourne 0 alors que ...
+            # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'etape est valide
+            # on peut donc le nommer sans test prealable
+            if self.parent.get_sd_autour_etape(nom,self):
+              return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
+            else:
+              # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
+              self.sd.nom=nom
+              self.sdnom=nom
+              self.parent.update_concept_after_etape(self,self.sd)
+              self.fin_modif()
+              return 1, tr("Nommage du concept effectue")
           if self.isvalid() :
             # Normalement l appel de isvalid a mis a jour le concept produit (son type)
           if self.isvalid() :
             # Normalement l appel de isvalid a mis a jour le concept produit (son type)
-            # Il suffit de spécifier l attribut nom de sd pour le nommer si le nom n est pas
-            # deja attribué
+            # Il suffit de specifier l attribut nom de sd pour le nommer si le nom n est pas
+            # deja attribue
             if self.parent.get_sd_autour_etape(nom,self):
             if self.parent.get_sd_autour_etape(nom,self):
-              return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
+              return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
             else:
             else:
+              # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
               self.sd.nom=nom
               self.sdnom=nom
               self.sd.nom=nom
               self.sdnom=nom
-              return 1,"Nommage du concept effectué"
+              self.parent.update_concept_after_etape(self,self.sd)
+              self.fin_modif()
+              return 1, tr("Nommage du concept effectue")
           else:
             # Normalement on ne devrait pas passer ici
           else:
             # Normalement on ne devrait pas passer ici
-            return 0,'Normalement on ne devrait pas passer ici'
+            return 0, 'Normalement on ne devrait pas passer ici'
 
    def get_sdprods(self,nom_sd):
       """ 
          Fonction : retourne le concept produit par l etape de nom nom_sd
 
    def get_sdprods(self,nom_sd):
       """ 
          Fonction : retourne le concept produit par l etape de nom nom_sd
-                    s il existe sinon None
+         s il existe sinon None
       """
       if self.sd:
         if self.sd.nom == nom_sd:return self.sd
       """
       if self.sd:
         if self.sd.nom == nom_sd:return self.sd
@@ -188,15 +219,18 @@ class ETAPE(I_MCCOMPO.MCCOMPO):
       """
           Rend l'etape courante active.
           Il faut ajouter la sd si elle existe au contexte global du JDC
       """
           Rend l'etape courante active.
           Il faut ajouter la sd si elle existe au contexte global du JDC
-          et à la liste des sd
+          et a la liste des sd
       """
       """
+      if self.actif:return
       self.actif = 1
       self.actif = 1
-      if not self.sd : return
-      # XXX Pourquoi faut-il faire ce qui suit ??? par defaut les etapes sont actives
-      try:
-        self.jdc.append_sdprod(self.sd)
-      except:
-        pass
+      self.init_modif()
+      if self.sd :
+        try:
+          self.jdc.append_sdprod(self.sd)
+        except:
+          pass
+      CONNECTOR.Emit(self,"add",None)
+      CONNECTOR.Emit(self,"valid")
 
    def inactive(self):
       """
 
    def inactive(self):
       """
@@ -205,38 +239,83 @@ class ETAPE(I_MCCOMPO.MCCOMPO):
           et de la liste des sd
       """
       self.actif = 0
           et de la liste des sd
       """
       self.actif = 0
-      if not self.sd : return
-      self.jdc.del_sdprod(self.sd)
-      self.jdc.delete_concept_after_etape(self,self.sd)
+      self.init_modif()
+      if self.sd :
+         self.jdc.del_sdprod(self.sd)
+         self.jdc.delete_concept_after_etape(self,self.sd)
+      CONNECTOR.Emit(self,"supp",None)
+      CONNECTOR.Emit(self,"valid")
+
+   def control_sdprods(self,d):
+      """
+          Cette methode doit verifier que ses concepts produits ne sont pas
+          deja definis dans le contexte
+          Si c'est le cas, les concepts produits doivent etre supprimes
+      """
+      #print "control_sdprods",d.keys(),self.sd and self.sd.nom,self.nom
+      if self.sd:
+        if d.has_key(self.sd.nom):
+           # Le concept est deja defini
+           if self.reuse and self.reuse is d[self.sd.nom]:
+              # Le concept est reutilise : situation normale
+              pass
+           else:
+              # Redefinition du concept, on l'annule
+              #XXX on pourrait simplement annuler son nom pour conserver les objets
+              # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
+              self.init_modif()
+              sd=self.sd
+              self.sd=self.reuse=self.sdnom=None
+              #supprime les references a sd dans les etapes suivantes
+              self.parent.delete_concept_after_etape(self,sd)
+              self.fin_modif()
+
+   def supprime_sdprod(self,sd):
+      """
+         Supprime le concept produit sd s'il est produit par l'etape
+      """
+      if sd is not self.sd:return
+      if self.sd != None :
+         self.init_modif()
+         self.parent.del_sdprod(sd)
+         self.sd=None
+         self.fin_modif()
+         self.parent.delete_concept(sd)
 
    def supprime_sdprods(self):
       """ 
 
    def supprime_sdprods(self):
       """ 
-          Fonction:
+            Fonction:
             Lors d'une destruction d'etape, detruit tous les concepts produits
             Lors d'une destruction d'etape, detruit tous les concepts produits
-            Un opérateur n a qu un concept produit 
+            Un operateur n a qu un concept produit 
             Une procedure n'en a aucun
             Une procedure n'en a aucun
-            Une macro en a en général plus d'un
+            Une macro en a en general plus d'un
       """
       """
-      # XXX pour les macros il faudrait peut etre aussi 
-      #     supprimer les concepts a droite du = ???
-      if not self.is_reentrant() :
-        # l'étape n'est pas réentrante
-        # le concept retourné par l'étape est à supprimer car il était 
-        # créé par l'étape
-        if self.sd != None :
-          self.parent.del_sdprod(self.sd)
-          self.parent.delete_concept(self.sd)
+      #print "supprime_sdprods",self
+      if self.reuse is self.sd :return
+      # l'etape n'est pas reentrante
+      # le concept retourne par l'etape est a supprimer car il etait 
+      # cree par l'etape
+      if self.sd != None :
+         self.parent.del_sdprod(self.sd)
+         self.parent.delete_concept(self.sd)
+
+   def close(self):
+      return
+
+   def update_concept(self,sd):
+      for child in self.mc_liste :
+          child.update_concept(sd)
 
    def delete_concept(self,sd):
       """ 
           Inputs :
 
    def delete_concept(self,sd):
       """ 
           Inputs :
-             sd=concept detruit
+             sd=concept detruit
           Fonction :
           Fonction :
-             Mettre a jour les mots cles de l etape et eventuellement 
-             le concept produit si reuse
-             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 mots cles de l etape et eventuellement 
+          le concept produit si reuse
+          suite a la disparition du concept sd
+          Seuls les mots cles simples MCSIMP font un traitement autre 
+          que de transmettre aux fils
       """
       if self.reuse and self.reuse == sd:
         self.sd=self.reuse=None
       """
       if self.reuse and self.reuse == sd:
         self.sd=self.reuse=None
@@ -244,51 +323,28 @@ class ETAPE(I_MCCOMPO.MCCOMPO):
       for child in self.mc_liste :
         child.delete_concept(sd)
 
       for child in self.mc_liste :
         child.delete_concept(sd)
 
-   def make_register(self):
+   def replace_concept(self,old_sd,sd):
       """
       """
-         Initialise les attributs jdc, id, niveau et réalise les
-         enregistrements nécessaires
-         Pour EFICAS, on tient compte des niveaux
-         Surcharge la methode make_register du package Noyau
+          Inputs :
+             - old_sd=concept remplace
+             - sd = nouveau concept 
+          Fonction :
+          Mettre a jour les mots cles de l etape et eventuellement
+          le concept produit si reuse
+          suite au remplacement  du concept old_sd
       """
       """
-      if self.parent :
-         self.jdc = self.parent.get_jdc_root()
-         self.id=   self.parent.register(self)
-         if self.definition.niveau :
-            # La définition est dans un niveau. En plus on
-            # l'enregistre dans le niveau
-            self.nom_niveau_definition = self.definition.niveau.nom
-            self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
-            self.niveau.register(self)
-         else:
-            # La définition est au niveau global
-            self.nom_niveau_definition = 'JDC'
-            self.niveau=self.parent
-      else:
-         self.jdc = self.parent =None
-         self.id=None
-         self.niveau=None
+      if self.reuse and self.reuse == old_sd:
+        self.sd=self.reuse=sd
+        self.init_modif()
+      for child in self.mc_liste :
+        child.replace_concept(old_sd,sd)
 
 
-   def copy(self):
-      """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
-          et sans sd 
-      """
-      etape = copy(self)
-      etape.sd = None
-      etape.state = 'modified'
-      etape.reuse = None
-      etape.sdnom = None
-      etape.etape=etape
-      etape.mc_liste=[]
-      for objet in self.mc_liste:
-        new_obj = objet.copy()
-        new_obj.reparent(etape)
-        etape.mc_liste.append(new_obj)
-      return etape
+   def reset_context(self):
+      pass
 
    def get_noms_sd_oper_reentrant(self):
       """ 
 
    def get_noms_sd_oper_reentrant(self):
       """ 
-          Retourne la liste des noms de concepts utilisés à l'intérieur de la commande
+          Retourne la liste des noms de concepts utilisesa l'interieur de la commande
           qui sont du type que peut retourner cette commande 
       """
       liste_sd = self.get_sd_utilisees()
           qui sont du type que peut retourner cette commande 
       """
       liste_sd = self.get_sd_utilisees()
@@ -306,114 +362,125 @@ class ETAPE(I_MCCOMPO.MCCOMPO):
       l_noms.sort()
       return l_noms
 
       l_noms.sort()
       return l_noms
 
-   def get_sd_utilisees(self):
-      """ 
-          Retourne la liste des concepts qui sont utilisés à l'intérieur d'une commande
-          ( comme valorisation d'un MCS) 
-      """
-      l=[]
-      for child in self.mc_liste:
-        l.extend(child.get_sd_utilisees())
-      return l
-
    def get_genealogie(self):
       """ 
           Retourne la liste des noms des ascendants de l'objet self
    def get_genealogie(self):
       """ 
           Retourne la liste des noms des ascendants de l'objet self
-          en s'arretant à la première ETAPE rencontrée
+          en s'arretant a la premiere ETAPE rencontree
       """
       return [self.nom]
 
       """
       return [self.nom]
 
-   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=self
-     for mocle in self.mc_liste:
-        mocle.reparent(self)
-
    def verif_existence_sd(self):
      """
    def verif_existence_sd(self):
      """
-        Vérifie que les structures de données utilisées dans self existent bien dans le contexte
-       avant étape, sinon enlève la référence à ces concepts
+        Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
+        avant etape, sinon enleve la referea ces concepts
      """
      """
+     #print "verif_existence_sd",self.sd
      for motcle in self.mc_liste :
          motcle.verif_existence_sd()
      for motcle in self.mc_liste :
          motcle.verif_existence_sd()
+
+   def update_mc_global(self):
+     """
+        Met a jour les mots cles globaux enregistres dans l'etape
+        et dans le jdc parent.
+        Une etape ne peut pas etre globale. Elle se contente de passer
+        la requete a ses fils apres avoir reinitialise le dictionnaire 
+        des mots cles globaux.
+     """
+     self.mc_globaux={}
+     I_MCCOMPO.MCCOMPO.update_mc_global(self)
+
+   def update_condition_bloc(self):
+     """
+        Realise l'update des blocs conditionnels fils de self
+     """
+     self._update_condition_bloc()
+
+   def get_objet_commentarise(self,format):
+      """
+          Cette methode retourne un objet commande commentarisee
+          representant la commande self
+      """
+      import generator
+      g=generator.plugins[format]()
+      texte_commande = g.gener(self,format='beautifie')
+      # Il faut enlever la premiere ligne vide de texte_commande que
+      # rajoute le generator
+      #rebut,texte_commande = string.split(texte_commande,'\n',1)
+      # on construit l'objet COMMANDE_COMM repesentatif de self mais non
+      # enregistre dans le jdc (pas ajoute dans jdc.etapes)
+      parent=self.parent
+      pos=self.parent.etapes.index(self)
+      commande_comment = commande_comm.COMMANDE_COMM(texte=texte_commande,
+                                                     reg='non',
+                                                     parent=parent)
+      self.parent.suppentite(self)
+      parent.addentite(commande_comment,pos)
+
+      return commande_comment
+
+   def modified(self):
+      """Le contenu de l'etape (mots cles, ...) a ete modifie"""
+      if self.nom=="DETRUIRE":
+        self.parent.control_context_apres(self)
+
+
      
      
+#ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau
    def Build_sd(self,nom):
       """
    def Build_sd(self,nom):
       """
-         Construit le concept produit de l'opérateur. Deux cas 
-         peuvent se présenter :
-        
-         - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création 
-           et le nommage du concept.
+           Methode de Noyau surchargee pour poursuivre malgre tout
+           si une erreur se produit pendant la creation du concept produit
+      """
+      try:
+         sd=Noyau.N_ETAPE.ETAPE.Build_sd(self,nom)
+      except AsException,e :
+         # Une erreur s'est produite lors de la construction du concept
+         # Comme on est dans EFICAS, on essaie de poursuivre quand meme
+         # Si on poursuit, on a le choix entre deux possibilites :
+         # 1. on annule la sd associee a self
+         # 2. on la conserve mais il faut la retourner
+         # En plus il faut rendre coherents sdnom et sd.nom
+         self.sd=None
+         self.sdnom=None
+         self.state="unchanged"
+         self.valid=0
 
 
-         - le parent est défini. Dans ce cas, l'étape demande au parent la création et 
-           le nommage du concept.
+      return self.sd
 
 
+#ATTENTION SURCHARGE: cette methode doit etre gardee en synchronisation avec Noyau
+   def make_register(self):
       """
       """
-      if not self.isactif():return
-      # FR : attention cette méthode ne devrait pas se trouver là car elle surcharge celle qui 
-      # se trouve dans N_ETAPE.py et elle est partie intégrante du noyau, mais, suite à l'absence de 
-      # test de validité de l'opérateur avant d'essayer de déterminer la sd produite, on n'arrivait
-      # pas à relire avec EFICAS un fichier contenant une étape encore incomplète du style :
-      #  sansnom = AFFE_CHAR_CINE(MODELE=None)
-      # Suite à la stabilisation du noyau d'Aster, je n'ai pas eu d'autre solution que de surcharger
-      # cette méthode ici en rajoutant le test manquant ...
-      # CCAR : cette modification ne corrige le probleme qu'en partie. Il faudrait probablement
-      # supprimer les erreurs fatales (exception ) et retourner systematiquement un objet produit
-      # meme en cas d'erreur et reporter l'emission du message d'erreur a la phase de validation
-      if not self.isvalid(sd='non') : return
-      else:self.state='undetermined'
-      self.sdnom=nom
-      try:
-         if self.parent:
-            sd= self.parent.create_sdprod(self,nom)
-            if type(self.definition.op_init) == types.FunctionType: 
-               apply(self.definition.op_init,(self,self.parent.g_context))
+         Initialise les attributs jdc, id, niveau et realise les
+         enregistrements necessaires
+         Pour EFICAS, on tient compte des niveaux
+         Surcharge la methode make_register du package Noyau
+      """
+      if self.parent :
+         self.jdc = self.parent.get_jdc_root()
+         self.id=   self.parent.register(self)
+         self.UserError=self.jdc.UserError
+         if self.definition.niveau :
+            # La definition est dans un niveau. En plus on
+            # l'enregistre dans le niveau
+            self.nom_niveau_definition = self.definition.niveau.nom
+            self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
+            self.niveau.register(self)
          else:
          else:
-            sd=self.get_sd_prod()
-            # On n'utilise pas self.definition.op_init car self.parent 
-            # n'existe pas
-            if sd != None and self.reuse == None:
-               # On ne nomme le concept que dans le cas de non reutilisation 
-               # d un concept
-               sd.nom=nom
-         if self.jdc and self.jdc.par_lot == "NON" :
-            self.Execute()
-         return sd
-      except AsException,e:
-         raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
-                              'fichier : ',self.appel[1],e)
-      except EOFError:
-         # XXX Normalement le contexte courant doit etre le parent.
-         # Il n'y a pas de raison de remettre le contexte au parent
-         #self.reset_current_step()
-         raise
-      except :
-         l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
-         raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
-                           'fichier : ',self.appel[1]+'\n',
-                            string.join(l))
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-     
-        
-     
+            # La definition est au niveau global
+            self.nom_niveau_definition = 'JDC'
+            self.niveau=self.parent
+      else:
+         self.jdc = self.parent =None
+         self.id=None
+         self.niveau=None
+         self.UserError="UserError"
+
+   def report(self):
+     cr= Validation.V_ETAPE.ETAPE.report(self)
+     #rafraichisst de la validite de l'etape (probleme avec l'ordre dans les macros : etape puis mots cles)
+     self.isvalid()
+     if not self.isvalid() and self.nom == "INCLUDE" :
+        self.cr.fatal(('Etape : %s ligne : %r  %s'),
+        self.nom, self.appel[0],  tr("\n   Include Invalide. \n  ne sera pas pris en compte"))
+     return cr
+