1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2017 EDF R&D
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 from __future__ import absolute_import
24 from __future__ import print_function
29 from Extensions.i18n import tr
30 from Extensions.eficas_exception import EficasException
32 # Objet re pour controler les identificateurs Python
33 concept_re=re.compile(r'[a-zA-Z_]\w*$')
35 # import rajoute suite a l'ajout de buildSd --> a resorber
38 from Noyau import N_Exception
39 from Noyau.N_Exception import AsException
41 # fin import a resorber
44 from . import I_MCCOMPO
45 from . import CONNECTOR
46 from Extensions import commande_comm
48 class ETAPE(I_MCCOMPO.MCCOMPO):
54 #print "SDNAME ",self.reuse,self.sd,self.sd.getName()
56 print(("SDNAME ", self.reuse, self.sd, self.sd.getName()))
58 if self.reuse != None:
59 sdname= self.reuse.getName()
61 if self.sd:sdname=self.sd.getName()
62 if sdname.find('sansnom') != -1 or sdname.find('SD_') != -1:
63 # dans le cas ou la SD est 'sansnom' ou 'SD_' on retourne la chaine vide
67 def isReentrant(self):
69 Indique si la commande est reentrante
71 return self.definition.reentrant == 'o'
75 Met l'etat de l'etape a : modifie
76 Propage la modification au parent
78 # initModif doit etre appele avant de realiser une modification
79 # La validite devra etre recalculee apres cette modification
80 # mais dans l'appel a finModif pour preserver l'etat modified
81 # de tous les objets entre temps
82 #print "initModif",self,self.parent
83 self.state = 'modified'
85 self.parent.initModif()
89 Methode appelee une fois qu'une modification a ete faite afin de
90 declencher d'eventuels traitements post-modification
91 ex : INCLUDE et POURSUITE
92 Ne pas mettre de traitement qui risque d'induire des recursions (soit a peu pres rien)
94 CONNECTOR.Emit(self,"valid")
96 self.parent.finModif()
98 def nommeSd(self,nom) :
100 Cette methode a pour fonction de donner un nom (nom) au concept
101 produit par l'etape (self).
102 - si le concept n'existe pas, on essaye de le creer a condition que l'etape soit valide ET non reentrante)
103 - si il existe dea, on le renomme et on repercute les changements dans les autres etapes
104 Les valeurs de retour sont :
105 - 0 si le nommage n'a pas pu etre menea son terme,
106 - 1 dans le cas contraire
108 # Le nom d'un concept doit etre un identificateur Python (toujours vrai ?)
109 if not concept_re.match(nom):
110 return 0, tr("Un nom de concept doit etre un identificateur Python")
112 # pour eviter que le nom du concept soit le nom de la classe --> souci pour utiliser le concept
113 if (nom == self.definition.nom) : return (0, tr("un concept de type ")+ nom + tr(" ne peut pas se nommer ") + nom)
114 if ( nom in dir(self.jdc.cata)) : return (0, nom + tr("est un not reserve"))
115 #if (not isinstance(nom,str)) : return (0, tr("Le nom ") + nom + tr(" est un mot reserve"))
116 #if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
117 # return 0, tr("Nom de concept trop long (maxi 8 caracteres)")
121 # On verifie d'abord si les mots cles sont valides
123 if not self.isValid(sd='non') : return 0,"Nommage du concept refuse : l'operateur n'est pas valide"
125 # Cas particulier des operateurs obligatoirement reentrants
127 if self.definition.reentrant == 'o':
128 self.sd = self.reuse = self.jdc.getSdAvantEtape(nom,self)
130 self.sdnom=self.sd.nom
132 return 1, tr("Concept existant")
134 return 0, tr("Operateur reentrant mais concept non existant")
136 # Cas particulier des operateurs facultativement reentrants
139 if self.definition.reentrant == 'f' :
140 sd = self.jdc.getSdAvantEtape(nom,self)
142 if isinstance(sd,self.getType_produit()) :
143 self.sd = self.reuse = sd
146 return 1, tr("Operateur reentrant et concept existant trouve")
148 return 0, tr("Concept deja existant et de mauvais type")
150 # il faut enlever le lien vers une SD existante car si on passe ici
151 # cela signifie que l'operateur n'est pas utilise en mode reentrant.
152 # Si on ne fait pas cela, on risque de modifier une SD produite par un autre operateur
155 self.sd = self.reuse = self.sdnom = None
157 # On est dans le cas ou l'operateur n'est pas reentrant ou est facultativement reentrant
158 # mais est utilise en mode non reentrant
161 #Pas de concept produit preexistant
162 if self.parent.getSdAutourEtape(nom,self):
163 # Un concept de ce nom existe dans le voisinage de l'etape courante
164 # On retablit l'ancien concept reentrant s'il existait
166 self.sd=self.reuse=old_reuse
167 self.sdnom=old_reuse.nom
168 return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
170 # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
171 # On peut donc creer le concept retourne
172 # Il est cree sans nom mais enregistre dans la liste des concepts existants
175 # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
178 self.parent.updateConceptAfterEtape(self,self.sd)
180 return 1, tr("Nommage du concept effectue")
182 return 0, tr("Nommage impossible %s", str(sys.exc_info()[1]))
184 #Un concept produit preexiste
186 if old_nom.find('sansnom') :
187 # Dans le cas ou old_nom == sansnom, isValid retourne 0 alors que ...
188 # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'etape est valide
189 # on peut donc le nommer sans test prealable
190 if self.parent.getSdAutourEtape(nom,self):
191 return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
193 # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
196 self.parent.updateConceptAfterEtape(self,self.sd)
198 return 1, tr("Nommage du concept effectue")
200 # Normalement l appel de isValid a mis a jour le concept produit (son type)
201 # Il suffit de specifier l attribut nom de sd pour le nommer si le nom n est pas
203 if self.parent.getSdAutourEtape(nom,self):
204 return 0, tr("Nommage du concept refuse : un concept de meme nom existe deja")
206 # Renommage du concept : Il suffit de changer son attribut nom pour le nommer
209 self.parent.updateConceptAfterEtape(self,self.sd)
211 return 1, tr("Nommage du concept effectue")
213 # Normalement on ne devrait pas passer ici
214 return 0, 'Normalement on ne devrait pas passer ici'
216 def getSdprods(self,nom_sd):
218 Fonction : retourne le concept produit par l etape de nom nom_sd
219 s il existe sinon None
222 if self.sd.nom == nom_sd:return self.sd
226 Rend l'etape courante active.
227 Il faut ajouter la sd si elle existe au contexte global du JDC
235 self.jdc.appendSdProd(self.sd)
238 CONNECTOR.Emit(self,"add",None)
239 CONNECTOR.Emit(self,"valid")
243 Rend l'etape courante inactive
244 Il faut supprimer la sd du contexte global du JDC
245 et de la liste des sd
250 self.jdc.delSdprod(self.sd)
251 self.jdc.deleteConceptAfterEtape(self,self.sd)
252 CONNECTOR.Emit(self,"supp",None)
253 CONNECTOR.Emit(self,"valid")
255 def controlSdprods(self,d):
257 Cette methode doit verifier que ses concepts produits ne sont pas
258 deja definis dans le contexte
259 Si c'est le cas, les concepts produits doivent etre supprimes
261 #print "controlSdprods",d.keys(),self.sd and self.sd.nom,self.nom
263 if self.sd.nom in d :
264 # Le concept est deja defini
265 if self.reuse and self.reuse is d[self.sd.nom]:
266 # Le concept est reutilise : situation normale
269 # Redefinition du concept, on l'annule
270 #XXX on pourrait simplement annuler son nom pour conserver les objets
271 # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
274 self.sd=self.reuse=self.sdnom=None
275 #supprime les references a sd dans les etapes suivantes
276 self.parent.deleteConceptAfterEtape(self,sd)
279 def supprimeSdprod(self,sd):
281 Supprime le concept produit sd s'il est produit par l'etape
283 if sd is not self.sd:return
286 self.parent.delSdprod(sd)
289 self.parent.deleteConcept(sd)
291 def supprimeSdProds(self):
294 Lors d'une destruction d'etape, detruit tous les concepts produits
295 Un operateur n a qu un concept produit
296 Une procedure n'en a aucun
297 Une macro en a en general plus d'un
299 #print "supprimeSdProds",self
300 if self.reuse is self.sd :return
301 # l'etape n'est pas reentrante
302 # le concept retourne par l'etape est a supprimer car il etait
305 self.parent.delSdprod(self.sd)
306 self.parent.deleteConcept(self.sd)
311 def updateConcept(self,sd):
312 for child in self.mcListe :
313 child.updateConcept(sd)
315 def deleteConcept(self,sd):
320 Mettre a jour les mots cles de l etape et eventuellement
321 le concept produit si reuse
322 suite a la disparition du concept sd
323 Seuls les mots cles simples MCSIMP font un traitement autre
324 que de transmettre aux fils
326 if self.reuse and self.reuse == sd:
327 self.sd=self.reuse=None
329 for child in self.mcListe :
330 child.deleteConcept(sd)
332 def replaceConcept(self,old_sd,sd):
335 - old_sd=concept remplace
336 - sd = nouveau concept
338 Mettre a jour les mots cles de l etape et eventuellement
339 le concept produit si reuse
340 suite au remplacement du concept old_sd
342 if self.reuse and self.reuse == old_sd:
343 self.sd=self.reuse=sd
345 for child in self.mcListe :
346 child.replaceConcept(old_sd,sd)
348 def resetContext(self):
351 def getNomsSdOperReentrant(self):
353 Retourne la liste des noms de concepts utilisesa l'interieur de la commande
354 qui sont du type que peut retourner cette commande
356 liste_sd = self.getSd_utilisees()
358 if type(self.definition.sd_prod) == types.FunctionType:
359 d=self.creeDictValeurs(self.mcListe)
361 classe_sd_prod = self.definition.sd_prod(*(), **d)
365 classe_sd_prod = self.definition.sd_prod
367 if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
371 def getGenealogiePrecise(self):
374 def getGenealogie(self):
376 Retourne la liste des noms des ascendants de l'objet self
377 en s'arretant a la premiere ETAPE rencontree
381 def verifExistenceSd(self):
383 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
384 avant etape, sinon enleve la referea ces concepts
386 #print "verifExistenceSd",self.sd
387 for motcle in self.mcListe :
388 motcle.verifExistenceSd()
390 def updateMcGlobal(self):
392 Met a jour les mots cles globaux enregistres dans l'etape
393 et dans le jdc parent.
394 Une etape ne peut pas etre globale. Elle se contente de passer
395 la requete a ses fils apres avoir reinitialise le dictionnaire
396 des mots cles globaux.
399 I_MCCOMPO.MCCOMPO.updateMcGlobal(self)
401 def updateConditionBloc(self):
403 Realise l'update des blocs conditionnels fils de self
405 self._updateConditionBloc()
407 def getObjetCommentarise(self,format):
409 Cette methode retourne un objet commande commentarisee
410 representant la commande self
413 g=generator.plugins[format]()
414 texte_commande = g.gener(self,format='beautifie')
415 # Il faut enlever la premiere ligne vide de texte_commande que
416 # rajoute le generator
417 # on construit l'objet COMMANDE_COMM repesentatif de self mais non
418 # enregistre dans le jdc (pas ajoute dans jdc.etapes)
420 pos=self.parent.etapes.index(self)
421 # on ajoute une fin à la commande pour pouvoir en commenter 2
422 texte_commande+='\nFin Commentaire'
423 commande_comment = commande_comm.COMMANDE_COMM(texte=texte_commande,
426 self.parent.suppEntite(self)
427 parent.addEntite(commande_comment,pos)
429 return commande_comment
432 """Le contenu de l'etape (mots cles, ...) a ete modifie"""
433 if self.nom=="DETRUIRE":
434 self.parent.controlContextApres(self)
438 #ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau
439 def buildSd(self,nom):
441 Methode de Noyau surchargee pour poursuivre malgre tout
442 si une erreur se produit pendant la creation du concept produit
445 sd=Noyau.N_ETAPE.ETAPE.buildSd(self,nom)
446 except AsException as e :
447 # Une erreur s'est produite lors de la construction du concept
448 # Comme on est dans EFICAS, on essaie de poursuivre quand meme
449 # Si on poursuit, on a le choix entre deux possibilites :
450 # 1. on annule la sd associee a self
451 # 2. on la conserve mais il faut la retourner
452 # En plus il faut rendre coherents sdnom et sd.nom
455 self.state="unchanged"
460 #ATTENTION SURCHARGE: cette methode doit etre gardee en synchronisation avec Noyau
461 def makeRegister(self):
463 Initialise les attributs jdc, id, niveau et realise les
464 enregistrements necessaires
465 Pour EFICAS, on tient compte des niveaux
466 Surcharge la methode makeRegister du package Noyau
469 self.jdc = self.parent.getJdcRoot()
470 self.id= self.parent.register(self)
471 self.UserError=self.jdc.UserError
472 if self.definition.niveau :
473 # La definition est dans un niveau. En plus on
474 # l'enregistre dans le niveau
475 self.nom_niveau_definition = self.definition.niveau.nom
476 self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
477 self.niveau.register(self)
479 # La definition est au niveau global
480 self.nom_niveau_definition = 'JDC'
481 self.niveau=self.parent
483 self.jdc = self.parent =None
486 self.UserError="UserError"
489 cr= Validation.V_ETAPE.ETAPE.report(self)
490 #rafraichisst de la validite de l'etape (probleme avec l'ordre dans les macros : etape puis mots cles)
492 if not self.isValid() and self.nom == "INCLUDE" :
493 self.cr.fatal(('Etape : %s ligne : %r %s'),
494 self.nom, self.appel[0], tr("\n Include Invalide. \n ne sera pas pris en compte"))