Salome HOME
ead7ed13d5b21cfa9b9b9636c173ed3a2279b413
[tools/eficas.git] / Ihm / I_JDC.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 # Modules Python
24 import types,traceback
25 import string,linecache
26
27 # Modules Eficas
28 import I_OBJECT
29 from Noyau.N_ASSD import ASSD
30 from Noyau.N_ETAPE import ETAPE
31 from Noyau.N_Exception import AsException
32 from Extensions import commentaire,parametre,parametre_eval
33 import CONNECTOR
34
35 class JDC(I_OBJECT.OBJECT):
36    """
37    """
38    def __init__(self):
39       self.editmode=0
40       self.etapes_niveaux=[]
41       self.niveau=self
42       self.params=[]
43       self.fonctions=[]
44       self._etape_context=None
45       self.recorded_units={}
46       self.old_recorded_units={}
47
48    def get_index(self,objet):
49       """
50         Retourne la position d'objet dans la liste self
51       """
52       return self.etapes.index(objet)
53
54    def get_sd_avant_du_bon_type(self,etape,types_permis):
55       """
56           Retourne la liste des concepts avant etape d'un type acceptable
57       """
58       d=self.get_contexte_avant(etape)
59       l=[]
60       for k,v in d.items():
61         if type(v) != types.InstanceType : continue
62         # On considère que seul assd indique un type quelconque pas CO
63         elif self.assd in types_permis :
64            l.append(k)
65         elif self.est_permis(v,types_permis):
66            l.append(k)
67       l.sort()
68       return l
69
70    def est_permis(self,v,types_permis):
71       for type_ok in types_permis:
72           if type_ok in ('R','I','C','TXM') and v in self.params : 
73              return 1
74           elif type_ok == 'R' and v.__class__.__name__ == 'reel' : 
75              return 1
76           elif type_ok == 'I' and v.__class__.__name__ == 'entier' : 
77              return 1
78           elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : 
79              return 1
80           elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : 
81              return 1
82           elif type(type_ok) != types.ClassType : 
83              continue
84           elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
85              return 1
86       return 0
87
88    def addentite(self,name,pos):
89       """
90           Ajoute une entite :
91           Si name est le nom d une commande ou un commentaire ajoute 
92           une etape au JDC
93           Sinon remonte une erreur
94       """
95       self.init_modif()
96       self.editmode=1
97       if name == "COMMENTAIRE" :
98         # ajout d'un commentaire
99         self.set_current_step()
100         ind = 1
101         for child in self.etapes :
102           if isinstance(child,commentaire.COMMENTAIRE):
103             ind = ind+1
104         objet = commentaire.COMMENTAIRE('',parent=self)
105         objet.nom = "_comm_"+`ind`
106         if pos == None : pos = 0
107         self.etapes.insert(pos,objet)
108         self.editmode=0
109         self.active_etapes()
110         CONNECTOR.Emit(self,"add",objet)
111         self.fin_modif()
112         return objet
113       elif name == "PARAMETRE":
114         # ajout d'un parametre
115         self.set_current_step()
116         nom_param = '_param_'+str(len(self.params)+1)
117         objet = parametre.PARAMETRE(nom=nom_param)
118         if pos == None : pos = 0
119         self.etapes.insert(pos,objet)
120         self.editmode=0
121         self.reset_context()
122         self.active_etapes()
123         CONNECTOR.Emit(self,"add",objet)
124         self.fin_modif()
125         return objet
126       elif name == "PARAMETRE_EVAL":
127         # ajout d'un parametre EVAL
128         self.set_current_step()
129         nom_param = '_param_'+str(len(self.params)+1)
130         objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
131         if pos == None : pos = 0
132         self.etapes.insert(pos,objet)
133         self.editmode=0
134         self.reset_context()
135         self.active_etapes()
136         CONNECTOR.Emit(self,"add",objet)
137         self.fin_modif()
138         return objet
139       elif type(name)==types.InstanceType:
140         # on est dans le cas où on veut ajouter une commande déjà 
141         # existante (par copie donc)
142         # on est donc nécessairement en mode editeur ...
143         objet = name
144         # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
145         #if hasattr(objet,'sd'):print "addentite",objet.sd
146         objet.reparent(self)
147         #if hasattr(objet,'sd'):print "addentite",objet.sd
148         self.set_current_step()
149         if isinstance(objet,ETAPE):
150           if objet.nom_niveau_definition == 'JDC':
151             # l'objet dépend directement du JDC
152             objet.niveau = self
153           else:
154             # l'étape dépend d'un niveau et non directement du JDC :
155             # il faut l'enregistrer dans le niveau de parent
156             objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
157             objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
158         self.etapes.insert(pos,objet)
159         # il faut vérifier que les concepts utilisés par objet existent bien
160         # à ce niveau d'arborescence
161         #if hasattr(objet,'sd'):print "addentite",objet.sd
162         objet.verif_existence_sd()
163         self.active_etapes()
164         self.editmode=0
165         self.reset_context()
166         #print "addentite",self.etapes
167         CONNECTOR.Emit(self,"add",objet)
168         self.fin_modif()
169         return objet
170       else :
171         # On veut ajouter une nouvelle commande
172         try:
173           self.set_current_step()
174           cmd=self.get_cmd(name)
175           # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
176           # auprès du step courant car editmode vaut 1
177           # Par contre elle a le bon parent grace a set_current_step
178           e=cmd.make_objet()
179           if pos == None : pos = 0
180           self.etapes.insert(pos,e)
181           self.reset_current_step()
182           self.editmode=0
183           self.reset_context()
184           self.active_etapes()
185           #print "addentite",self.etapes
186           CONNECTOR.Emit(self,"add",e)
187           self.fin_modif()
188           return e
189         except AsException,e:
190           self.reset_current_step()
191           self.editmode=0
192           raise AsException("Impossible d ajouter la commande "+name + '\n' +str(e))
193         except:
194           traceback.print_exc()
195           self.reset_current_step()
196           self.editmode=0
197           raise AsException("Impossible d ajouter la commande "+name)
198
199    def close(self):
200       #print "JDC.close",self
201       for etape in self.etapes:
202           if hasattr(etape,"close"):etape.close()
203       CONNECTOR.Emit(self,"close")
204
205    def set_current_step(self):
206       CONTEXT.unset_current_step()
207       CONTEXT.set_current_step(self)
208
209    def reset_current_step(self):
210       CONTEXT.unset_current_step()
211
212    def liste_mc_presents(self):
213       return []
214
215    def get_sd_avant_etape(self,nom_sd,etape):
216       return self.get_contexte_avant(etape).get(nom_sd,None)
217
218    def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
219       """ 
220            Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement
221            définie apres etape en tenant compte des concepts detruits
222            Si avec vaut 'non' exclut etape de la recherche
223       """
224       #print "JDC.get_sd_apres_etape_avec_detruire",nom_sd,sd
225       ietap=self.etapes.index(etape)
226       if avec == 'non':ietap=ietap+1
227       d={nom_sd:sd}
228       for e in self.etapes[ietap:]:
229          if e.isactif():
230             e.update_context(d)
231             autre_sd=d.get(nom_sd,None)
232             if autre_sd is None:
233               # Le concept a ete detruit. On interrompt la recherche car il n'y a
234               # pas eu de redefinition du concept (il n'y a pas de conflit potentiel).
235               return None
236             if autre_sd is not sd :
237               # L'etape produit un concept different de meme nom. La situation n'est
238               # pas saine (sauf peut etre si reuse ???)
239               if hasattr(e,'reuse') and e.reuse == autre_sd:
240                  # Le concept etant reutilise, on interrompt la recherche. 
241                  # On considere qu'il n'y a pas de nouveau concept defini
242                  # meme si dans les etapes suivantes le concept est detruit
243                  # et un concept de meme nom créé.
244                  # AVERIFIER : avec reuse le concept devrait etre le meme
245                  # le passage par ici est tres improbable
246                  return None
247               else:
248                  # Le concept est produit par l'etape (Il y a conflit potentiel).
249                  # Le concept est redefini par une etape posterieure.
250                  return autre_sd
251       # Pas de destruction du concept ni de redefinition. On retourne le
252       # concept initial
253       return sd
254
255    def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
256       """ 
257            Cette méthode retourne la SD de nom nom_sd qui est éventuellement
258            définie apres etape 
259            Si avec vaut 'non' exclut etape de la recherche
260       """
261       ietap=self.etapes.index(etape)
262       if avec == 'non':ietap=ietap+1
263       for e in self.etapes[ietap:]:
264         sd=e.get_sdprods(nom_sd)
265         if sd:
266           if hasattr(e,'reuse'):
267             if e.reuse != sd:
268               return sd
269       return None
270
271    def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
272       """
273            Fonction: retourne la SD de nom nom_sd qui est éventuellement
274            définie avant ou apres etape
275            Permet de vérifier si un concept de meme nom existe dans le périmètre 
276            d'une étape
277            Si avec vaut 'non' exclut etape de la recherche
278       """
279       sd=self.get_sd_avant_etape(nom_sd,etape)
280       if sd:return sd
281       return self.get_sd_apres_etape(nom_sd,etape,avec)
282
283    def get_contexte_apres(self,etape):
284       """
285          Retourne le dictionnaire des concepts connus apres etape
286          On tient compte des commandes qui modifient le contexte
287          comme DETRUIRE ou les macros
288          Si etape == None, on retourne le contexte en fin de JDC
289       """
290       if not etape: return self.get_contexte_avant(etape)
291
292       d=self.get_contexte_avant(etape)
293       if etape.isactif():etape.update_context(d)
294       self.index_etape_courante=self.index_etape_courante+1
295       return d
296
297    def active_etapes(self):
298       """
299           Cette méthode a pour fonction de désactiver les étapes qui doivent
300           l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas 
301           comprises entre le premier DEBUT/POURSUITE et le premier FIN 
302           et rendre actives les autres
303       """
304       if self.definition.code == 'ASTER' :
305          # Seulement pour ASTER :
306          # Avant DEBUT actif vaut 0
307          # Apres DEBUT et avant le 1er FIN actif vaut 1
308          # Apres le 1er FIN actif vaut -1
309          actif=0
310       else:
311          actif=1
312       for etape in self.etapes:
313         if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
314         if actif == 1:
315            etape.active()
316         else:
317            etape.inactive()
318         if etape.nom == 'FIN':actif=-1
319
320    def suppentite(self,etape) :
321       """  
322           Cette methode a pour fonction de supprimer une étape dans 
323           un jeu de commandes
324           Retourne 1 si la suppression a pu être effectuée,
325           Retourne 0 dans le cas contraire
326       """
327       #print "suppentite",self
328       self.init_modif()
329       # On memorise le contexte avant l'etape a supprimer
330       d=self.get_contexte_avant(etape)
331       index_etape=self.etapes.index(etape)
332       #print "suppentite",index_etape,d
333
334       self.etapes.remove(etape)
335       if etape.niveau is not self:
336         # Dans ce cas l'étape est enregistrée dans un niveau
337         # Il faut la désenregistrer
338         etape.niveau.unregister(etape)
339       etape.supprime_sdprods()
340       etape.close()
341       self.active_etapes()
342
343       # Apres suppression de l'etape il faut controler que les etapes
344       # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
345       for e in self.etapes[index_etape:]:
346          e.control_sdprods(d)
347       
348       self.reset_context()
349       CONNECTOR.Emit(self,"supp",etape)
350       self.fin_modif()
351       return 1
352
353    def analyse(self):
354       self.compile()
355       if not self.cr.estvide():return
356       self.exec_compile()
357       self.active_etapes()
358
359    def register_parametre(self,param):
360       """
361           Cette méthode sert à ajouter un paramètre dans la liste des paramètres
362       """
363       self.params.append(param)
364
365    def register_fonction(self,fonction):
366       """
367           Cette méthode sert à ajouter une fonction dans la liste des fonctions
368       """
369       self.fonctions.append(fonction)
370
371    def delete_param(self,param):
372       """
373           Supprime le paramètre param de la liste des paramètres
374           et du contexte gobal
375       """
376       if param in self.params : self.params.remove(param)
377       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
378
379    def get_parametres_fonctions_avant_etape(self,etape):
380       """
381           Retourne deux éléments :
382           - une liste contenant les noms des paramètres (constantes ou EVAL) 
383             définis avant etape
384           - une liste contenant les formules définies avant etape
385       """
386       l_constantes = []
387       l_fonctions = []
388       # on récupère le contexte avant etape
389       # on ne peut mettre dans les deux listes que des éléments de ce contexte
390       d=self.get_contexte_avant(etape)
391       # construction de l_constantes
392       for param in self.params:
393         nom = param.nom
394         if not nom : continue
395         if d.has_key(nom): l_constantes.append(nom)
396       # construction de l_fonctions
397       for form in self.fonctions:
398         nom = form.nom
399         if not nom : continue
400         if d.has_key(nom): l_fonctions.append(form.get_formule())
401
402       # on ajoute les concepts produits par DEFI_VALEUR
403       # XXX On pourrait peut etre faire plutot le test sur le type
404       # de concept : entier, reel, complexe, etc.
405       for k,v in d.items():
406          if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
407             l_constantes.append(k)
408
409       # on retourne les deux listes
410       return l_constantes,l_fonctions
411
412    def get_nb_etapes_avant(self,niveau):
413       """ 
414           Retourne le nombre d etapes avant le debut de niveau
415       """
416       nb=0
417       for niv in self.etapes_niveaux:
418         if niv == niveau:break
419         nb=nb+len(niv.etapes)
420       return nb
421
422    def send_message(self,message):
423       if self.appli:
424          self.appli.send_message(message)
425
426    def init_modif(self):
427       """
428       Méthode appelée au moment où une modification va être faite afin de 
429       déclencher d'éventuels traitements pré-modification
430       """
431       #print "init_modif",self
432       self.state = 'modified'
433
434    def fin_modif(self):
435       #print "fin_modif",self
436       CONNECTOR.Emit(self,"valid")
437       self.isvalid()
438       pass
439
440    def deep_update_condition_bloc(self):
441       # pour le moment, on ne fait rien
442       raise "Not implemented"
443
444    def update_condition_bloc(self):
445       # pour le moment, on ne fait rien
446       raise "Not implemented"
447
448    def get_liste_mc_inconnus(self):
449      """
450      Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
451      """
452      # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
453      l_mc = []
454      for etape in self.etapes :
455          if etape.isactif() :
456             if not etape.isvalid() :
457                l = etape.get_liste_mc_inconnus()
458                if l : l_mc.extend(l)
459      return l_mc    
460
461    def get_genealogie(self):
462       """
463           Retourne la liste des noms des ascendants de l'objet self
464           jusqu'à la première ETAPE parent.
465       """
466       return []
467
468    def get_liste_cmd(self):
469       """
470           Retourne la liste des commandes du catalogue
471       """
472       return self.niveau.definition.get_liste_cmd()
473
474    def get_groups(self):
475       """
476           Retourne la liste des groupes
477       """
478       return self.niveau.definition.liste_groupes,self.niveau.definition.dict_groupes
479
480    def set_etape_context(self,etape):
481       """
482           Positionne l'etape qui sera utilisee dans NommerSdProd pour
483           decider si le concept passé pourra etre  nommé
484       """
485       self._etape_context=etape
486
487    def reset_context(self):
488       """ 
489           Cette methode reinitialise le contexte glissant pour pouvoir
490           tenir compte des modifications de l'utilisateur : création
491           de commandes, nommage de concepts, etc.
492       """
493       self.current_context={}
494       self.index_etape_courante=0
495
496    def del_sdprod(self,sd):
497       """
498           Supprime la SD sd de la liste des sd et des dictionnaires de contexte
499       """
500       #print "del_sdprod",self,sd
501       #print "del_sdprod",self.sds
502       #print "del_sdprod",self.g_context
503       #print "del_sdprod",self.sds_dict
504       if sd in self.sds : self.sds.remove(sd)
505       if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
506       if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
507
508    def del_param(self,param):
509       """
510           Supprime le paramètre param de la liste des paramètres
511           et du contexte gobal
512       """
513       if param in self.params : self.params.remove(param)
514       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
515
516    def del_fonction(self,fonction):
517       """
518           Supprime la fonction fonction de la liste des fonctions
519           et du contexte gobal
520       """
521       if fonction in self.fonctions : self.fonctions.remove(fonction)
522       if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
523
524    def append_sdprod(self,sd):
525       """
526           Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
527           même nom n'existe pas déjà
528       """
529       if sd == None or sd.nom == None:return
530
531       o=self.sds_dict.get(sd.nom,None)
532       if isinstance(o,ASSD):
533          raise AsException("Nom de concept deja defini : %s" % sd.nom)
534       self.sds_dict[sd.nom]=sd
535       self.g_context[sd.nom] = sd
536       if sd not in self.sds : self.sds.append(sd)
537
538    def append_param(self,param):
539       """
540           Ajoute le paramètre param à la liste des params
541           et au contexte global
542       """
543       # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
544       if param not in self.params : self.params.append(param)
545       self.g_context[param.nom]=param
546
547    def append_fonction(self,fonction):
548       """
549           Ajoute la fonction fonction à la liste des fonctions
550           et au contexte global
551       """
552       # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
553       if fonction not in self.fonctions : self.fonctions.append(fonction)
554       self.g_context[fonction.nom]=fonction
555
556    def delete_concept(self,sd):
557       """
558           Inputs :
559              - sd=concept detruit
560           Fonction :
561           Mettre a jour les etapes du JDC suite à la disparition du
562           concept sd
563           Seuls les mots cles simples MCSIMP font un traitement autre
564           que de transmettre aux fils
565       """
566       #print "delete_concept",self,sd
567       for etape in self.etapes :
568         etape.delete_concept(sd)
569
570    def replace_concept_after_etape(self,etape,old_sd,sd):
571       """
572           Met à jour les étapes du JDC qui sont après etape en fonction
573           du remplacement du concept sd
574       """
575       index = self.etapes.index(etape)+1
576       if index == len(self.etapes) :
577          return # etape est la dernière étape du jdc ...on ne fait rien !
578       for child in self.etapes[index:]:
579         child.replace_concept(old_sd,sd)
580
581    def dump_state(self):
582       print "dump_state"
583       print "JDC.state: ",self.state
584       for etape in self.etapes :
585          print etape.nom+".state: ",etape.state
586       
587    def change_unit(self,unit,etape,old_unit):
588       #print "change_unit",unit,etape,old_unit
589       #print id(self.recorded_units),self.recorded_units
590       #if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
591       self.record_unit(unit,etape)
592
593    def record_unit(self,unit,etape):
594       """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
595       #print "record_unit",unit,etape
596       if unit is None:
597          # Cas de POURSUITE
598          self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
599       else:
600          self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
601       #print id(self.recorded_units),self.recorded_units
602       #print self.recorded_units.get(None,(None,"",{}))[2]
603       #print self.recorded_units.get(None,(None,"",{}))[2].get(None,(None,"",{}))
604
605 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
606    def register(self,etape):
607       """
608            Cette méthode ajoute  etape dans la liste
609            des etapes self.etapes et retourne l identificateur d'étape
610            fourni par l appel a g_register
611
612            A quoi sert editmode ?
613               - Si editmode vaut 1, on est en mode edition de JDC. On cherche
614                 à enregistrer une étape que l'on a créée avec eficas (en passant
615                 par addentite) auquel cas on ne veut récupérer que son numéro
616                 d'enregistrement et c'est addentité qui l'enregistre dans
617                 self.etapes à la bonne place...
618               - Si editmode vaut 0, on est en mode relecture d'un fichier de
619                 commandes et on doit enregistrer l'étape à la fin de self.etapes
620                 (dans ce cas l'ordre des étapes est bien l'ordre chronologique
621                 de leur création   )
622       """
623       if not self.editmode:
624          self.etapes.append(etape)
625       else:
626          pass
627       return self.g_register(etape)
628
629 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
630    def NommerSdprod(self,sd,sdnom,restrict='non'):
631       """
632           Nomme la SD apres avoir verifie que le nommage est possible :
633           nom non utilise
634           Si le nom est deja utilise, leve une exception
635           Met le concept créé dans le concept global g_context
636       """
637       # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
638       # Le dictionnaire g_context ne représente pas le contexte
639       # effectif avant une étape.
640       # Il faut utiliser get_contexte_avant avec indication de l'étape
641       # traitée.
642       # Cette etape est indiquee par l'attribut _etape_context qui a ete
643       # positionné préalablement par un appel à set_etape_context
644
645       if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
646
647       if self._etape_context:
648          o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
649       else:
650          o=self.sds_dict.get(sdnom,None)
651
652       if isinstance(o,ASSD):
653          raise AsException("Nom de concept deja defini : %s" % sdnom)
654
655       # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
656       # Ajoute a la creation (appel de reg_sd).
657       self.sds_dict[sdnom]=sd
658       sd.nom=sdnom
659
660       # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
661       if restrict == 'non':
662          self.g_context[sdnom]=sd
663
664 #ATTENTION SURCHARGE : cette methode doit etre gardée en synchronisation avec celle de Noyau
665    def delete_concept_after_etape(self,etape,sd):
666       """
667           Met à jour les étapes du JDC qui sont après etape en fonction
668           de la disparition du concept sd
669       """
670       index = self.etapes.index(etape)+1
671       if index == len(self.etapes) :
672          return # etape est la dernière étape du jdc ...on ne fait rien !
673       for child in self.etapes[index:]:
674         child.delete_concept(sd)
675
676 #ATTENTION SURCHARGE : les methodes ci-dessous surchargent des methodes de Noyau et Validation : a reintegrer
677