]> SALOME platform Git repositories - modules/yacs.git/blob - src/hmi/guiObservers.cxx
Salome HOME
[PYTHON 3] WIP
[modules/yacs.git] / src / hmi / guiObservers.cxx
1 // Copyright (C) 2006-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <Python.h>
21 #include "guiObservers.hxx"
22 #include "commandsProc.hxx"
23 #include "Node.hxx"
24 #include "ComposedNode.hxx"
25 #include "Bloc.hxx"
26 #include "Proc.hxx"
27 #include "ElementaryNode.hxx"
28 #include "InlineNode.hxx"
29 #include "ServiceNode.hxx"
30 #include "PythonNode.hxx"
31 #include "CORBANode.hxx"
32 #include "CppNode.hxx"
33 #include "XMLNode.hxx"
34 #include "SalomePythonNode.hxx"
35 #include "DataNode.hxx"
36 #include "PresetNode.hxx"
37 #include "OutNode.hxx"
38 #include "StudyNodes.hxx"
39 #include "ForLoop.hxx"
40 #include "ForEachLoop.hxx"
41 #include "WhileLoop.hxx"
42 #include "Switch.hxx"
43 #include "OptimizerLoop.hxx"
44 #include "InputPort.hxx"
45 #include "OutputPort.hxx"
46 #include "InputDataStreamPort.hxx"
47 #include "OutputDataStreamPort.hxx"
48 #include "SalomeHPContainer.hxx"
49 #include "SalomeContainer.hxx"
50 #include "SalomeComponent.hxx"
51 #include "ComponentDefinition.hxx"
52 #include "TypeCode.hxx"
53 #include "RuntimeSALOME.hxx"
54
55 #include "guiContext.hxx"
56
57 #include <string>
58 #include <sstream>
59 #include <vector>
60
61 //#define _DEVDEBUG_
62 #include "YacsTrace.hxx"
63
64 using namespace std;
65
66 using namespace YACS;
67 using namespace YACS::HMI;
68 using namespace YACS::ENGINE;
69
70 std::map<int, std::string> GuiObserver::_eventNameMap;
71
72 // ----------------------------------------------------------------------------
73
74 void Subject::erase(Subject* sub, Command *command, bool post)
75 {
76   Subject* parent =sub->getParent();
77   sub->clean(command);
78   delete sub;
79   if (!post) // --- avoid recursion in erase, see cleanPostErase
80     GuiContext::getCurrent()->getSubjectProc()->cleanPostErase();
81 }
82
83 // ----------------------------------------------------------------------------
84
85 Subject::Subject(Subject *parent) : _parent(parent)
86 {
87   _destructible = true;
88   _askRegisterUndo = false;
89 }
90
91 /*!
92  *  Destructor must only be called by Subject::erase to clean
93  *  completely the context (detach observers), before the delete
94  *  process itself. Some actions involving dynamic_cast can't be done
95  *  in destructor.
96  */
97 Subject::~Subject()
98 {
99   DEBTRACE("Subject::~Subject " << this << " "<< getName());
100 }
101
102 /*!
103  * Clean process prior to delete is redefined in derived classes: a local clean
104  * treatment relative to the derived class, then a call to the parent class clean
105  * method.
106  */
107 void Subject::clean(Command *command)
108 {
109   localclean(command);
110 }
111
112 /*!
113  *  the local clean method of base class of subjects take care of Observers.
114  *  Remaining Observers in the list are detached, if an observer has no more
115  *  Subject to observe, it can be deleted.
116  */
117 void Subject::localclean(Command *command)
118 {
119   DEBTRACE("Subject::localClean ");
120   set<GuiObserver*>::iterator it;
121   while (int nbObs = _setObs.size())
122     {
123       DEBTRACE("--- " << this << " nbObs " << nbObs);
124       set<GuiObserver*> copySet = _setObs;
125       for (it = copySet.begin(); it != copySet.end(); ++it)
126         {
127           GuiObserver* anObs = (*it);
128           detach(anObs);
129           int nbsub = anObs->getNbSubjects();
130           DEBTRACE("nbSubjects=" << nbsub << " obs=" << anObs);
131           if (nbsub <= 0 && anObs->isDestructible())
132             {
133               delete anObs ;
134               break; // --- each delete may induce remove of other observers
135             }
136         }
137     }
138   _setObs.clear();
139 }
140
141 void Subject::registerUndoDestroy()
142 {
143   DEBTRACE("Subject::registerUndoDestroy");
144 }
145
146 void Subject::attach(GuiObserver *obs)
147 {
148   DEBTRACE("Subject::attach " << obs);
149   _setObs.insert(obs);
150   obs->incrementSubjects(this);
151 }
152
153 void Subject::detach(GuiObserver *obs)
154 {
155   DEBTRACE("Subject::detach " << obs);
156   obs->decrementSubjects(this);
157   _setObs.erase(obs);
158 }
159
160 std::string Subject::getName()
161 {
162   return "generic";
163 }
164
165 bool Subject::setName(std::string name)
166 {
167   return false;
168 }
169
170 std::map<std::string, std::string> Subject::getProperties()
171 {
172   std::map<std::string, std::string> empty;
173   return empty;
174 }
175
176 bool Subject::setProperties(std::map<std::string, std::string> properties)
177 {
178   return true;
179 }
180
181 std::vector<std::string> Subject::knownProperties()
182 {
183   std::vector<std::string> empty;
184   return empty;
185 }
186
187 void Subject::select(bool isSelected)
188 {
189   DEBTRACE("Subject::select " << isSelected << " " << this);
190   set<GuiObserver*> copySet = _setObs;
191   for (set<GuiObserver *>::iterator it = copySet.begin(); it != copySet.end(); ++it)
192     {
193       GuiObserver* currOb = *it;
194       currOb->select(isSelected);
195     }
196 }
197
198 void Subject::update(GuiEvent event,int type, Subject* son)
199 {
200     std::cerr << "Subject::update " << type << "," << GuiObserver::eventName(event) << "," << son << std::endl;
201   set<GuiObserver*> copySet = _setObs;
202   for (set<GuiObserver *>::iterator it = copySet.begin(); it != copySet.end(); ++it)
203     {
204         std::cerr << "Subject::update " << *it << std::endl;
205       try
206         {
207           (*it)->update(event, type, son);
208         }
209       catch(Exception& ex)
210         {
211           std::cerr << "Internal error in Subject::update: " << ex.what() << std::endl;
212           std::cerr << "ERREUR ICI" << std::endl;
213         }
214       //catch(...)
215       //  {
216       //    std::cerr << "Internal error in Subject::update: " << std::endl;
217       //    std::cerr << "ERREUR OU LA " << std::endl;
218       //  }
219     }
220 }
221
222 Subject* Subject::getParent()
223 {
224   return _parent;
225 }
226
227 void Subject::setParent(Subject* son)
228 {
229   _parent=son;
230 }
231
232 //! From user action in Ihm, destroy an object
233 /*!
234  *  Called from GuiEditor::DeleteSubject(parent, toRemove).
235  *  The subject (this) is the parent of the subject (son) to remove.
236  *  Son must represent a Node, a DataPort, a Link or a ControlLink.
237  *  All other objects can only be destroyed automatically, not via an user command.
238  *  Only the destruction originated from user, using this method, are registered for undo-redo.
239  */
240 bool Subject::destroy(Subject *son)
241 {
242   string toDestroy = son->getName();
243   DEBTRACE("Subject::destroy " << toDestroy);
244   Proc *proc = GuiContext::getCurrent()->getProc();
245   string startnode = "";
246   string endnode = "";
247   string startport = "";
248   string endport = "";
249   TypeOfElem startportType = UNKNOWN;
250   TypeOfElem endportType = UNKNOWN;
251
252   if (dynamic_cast<SubjectProc*>(son))
253     startnode = proc->getName();
254   else
255     {
256       if (SubjectNode *subNode = dynamic_cast<SubjectNode*>(son))
257         {
258           if (subNode->getNode()->getFather() )
259             startnode = proc->getChildName(subNode->getNode());
260         }
261       else if (dynamic_cast<SubjectDataPort*>(son))
262         {
263           SubjectNode *subNodep = dynamic_cast<SubjectNode*>(son->getParent());
264           startnode = proc->getChildName(subNodep->getNode());
265           startport = son->getName();
266           startportType = son->getType();
267         }
268       else if (SubjectLink* slink = dynamic_cast<SubjectLink*>(son))
269         {
270           startnode = proc->getChildName(slink->getSubjectOutNode()->getNode());
271           endnode = proc->getChildName(slink->getSubjectInNode()->getNode());
272           startport = slink->getSubjectOutPort()->getName();
273           endport = slink->getSubjectInPort()->getName();
274           startportType = slink->getSubjectOutPort()->getType();
275           endportType = slink->getSubjectInPort()->getType();
276         }
277       else if (SubjectControlLink* sclink = dynamic_cast<SubjectControlLink*>(son))
278         {
279           startnode = proc->getChildName(sclink->getSubjectOutNode()->getNode());
280           endnode = proc->getChildName(sclink->getSubjectInNode()->getNode());
281         }
282       else if (SubjectContainerBase* scont = dynamic_cast<SubjectContainerBase*>(son))
283         {
284           if(scont->getName() == "DefaultContainer")
285             {
286               GuiContext::getCurrent()->_lastErrorMessage = "You can't delete the default container";
287               return false;
288             }
289           if(scont->isUsed())
290             {
291               GuiContext::getCurrent()->_lastErrorMessage = "You can't delete a container that contains components";
292               return false;
293             }
294           startnode = scont->getName();
295         }
296       else
297         {
298           GuiContext::getCurrent()->_lastErrorMessage = "No command Destroy for that type";
299           return false;
300         }
301     }
302   if (son->isDestructible())
303     {
304       CommandDestroy* command = new CommandDestroy(son->getType(), startnode, startport, startportType, endnode, endport, endportType);
305       if (command->execute())
306         {
307           DEBTRACE("Destruction done: " << toDestroy);
308           GuiContext::getCurrent()->getInvoc()->add(command);
309           return true;
310         }
311       else delete command;
312     }
313   return false;
314 }
315
316 void Subject::loadChildren()
317 {
318 }
319
320 void Subject::loadLinks()
321 {
322 }
323
324 void Subject::addSubjectReference(Subject *ref)
325 {
326   DEBTRACE("Subject::addSubjectReference " << getName() << " " << ref->getName());
327   SubjectReference *son = new SubjectReference(ref, this);
328   update(ADDREF, 0, son);
329 }
330
331 void Subject::setProgress( std::string newProgress )
332 {
333   _progress = newProgress;
334 }
335
336 // ----------------------------------------------------------------------------
337
338 GuiObserver::GuiObserver()
339   : _destructible(true)
340 {
341   //DEBTRACE("GuiObserver::GuiObserver " << this);
342   _subjectSet.clear();
343 }
344
345 GuiObserver::~GuiObserver()
346 {
347   DEBTRACE("GuiObserver::~GuiObserver " << this);
348   set<Subject*> subsetcpy = _subjectSet;
349   set<Subject*>::iterator it= subsetcpy.begin();
350   for (; it != subsetcpy.end(); ++it)
351     (*it)->detach(this);
352 }
353
354 void GuiObserver::select(bool isSelected)
355 {
356   DEBTRACE("GuiObserver::select() " << isSelected);
357 }
358
359 void GuiObserver::update(GuiEvent event, int type,  Subject* son)
360 {
361   //DEBTRACE("GuiObserver::update, event not handled " << eventName(event) << " " << type );
362 }
363
364 /*!
365  * only called by subject when attach to subject.
366  * @see Subject::attach
367  */
368 void GuiObserver::incrementSubjects(Subject *subject)
369 {
370   if (_subjectSet.count(subject))
371     DEBTRACE("subject " << subject << " is already a subject of observer " << this << "---------------------------");
372   _subjectSet.insert(subject);
373   //DEBTRACE(this << " " << _subjectSet.size());
374 }
375
376 /*!
377  * only called by subject when detach from subject.
378  * @see Subject::detach
379  */
380 void GuiObserver::decrementSubjects(Subject *subject)
381 {
382   if (_subjectSet.count(subject))
383     _subjectSet.erase(subject);
384   else
385     DEBTRACE("subject " << subject << " is not a subject of observer " << this << "---------------------------");
386   //DEBTRACE(this << " " << _subjectSet.size());
387 }
388
389 /*! 
390  * Gets the number of subjects observed.
391  * used by subject. When the subject is erased (Subject::erase),
392  * remaining observers are detached from subjects. If an observer has no
393  * more subject, it can be deleted.
394  * @see Subject::erase Subject::localClean
395  */
396 int GuiObserver::getNbSubjects()
397 {
398   return _subjectSet.size();
399 }
400
401 void GuiObserver::setEventMap()
402 {
403   _eventNameMap.clear();
404   _eventNameMap[ADD]            = "ADD";
405   _eventNameMap[REMOVE]         = "REMOVE";
406   _eventNameMap[CUT]            = "CUT";
407   _eventNameMap[PASTE]          = "PASTE";
408   _eventNameMap[ORDER]          = "ORDER";
409   _eventNameMap[EDIT]           = "EDIT";
410   _eventNameMap[UPDATE]         = "UPDATE";
411   _eventNameMap[UPDATEPROGRESS] = "UPDATEPROGRESS";
412   _eventNameMap[SYNCHRO]        = "SYNCHRO";
413   _eventNameMap[UP]             = "UP";
414   _eventNameMap[DOWN]           = "DOWN";
415   _eventNameMap[RENAME]         = "RENAME";
416   _eventNameMap[NEWROOT]        = "NEWROOT";
417   _eventNameMap[ENDLOAD]        = "ENDLOAD";
418   _eventNameMap[ADDLINK]        = "ADDLINK";
419   _eventNameMap[ADDCONTROLLINK] = "ADDCONTROLLINK";
420   _eventNameMap[ADDREF]         = "ADDREF";
421   _eventNameMap[ADDCHILDREF]    = "ADDCHILDREF";
422   _eventNameMap[REMOVECHILDREF] = "REMOVECHILDREF";
423   _eventNameMap[ASSOCIATE]      = "ASSOCIATE";
424   _eventNameMap[SETVALUE]       = "SETVALUE";
425   _eventNameMap[SETCASE]        = "SETCASE";
426   _eventNameMap[SETSELECT]      = "SETSELECT";
427   _eventNameMap[GEOMETRY]       = "GEOMETRY";
428 }
429
430 std::string GuiObserver::eventName(GuiEvent event)
431 {
432   if (_eventNameMap.count(event))
433     return _eventNameMap[event];
434   else return "Unknown Event";
435 }
436
437 // ----------------------------------------------------------------------------
438
439 SubjectObserver::SubjectObserver(Subject* ref):_reference(ref)
440 {
441 }
442 SubjectObserver::~SubjectObserver()
443 {
444 }
445 void SubjectObserver::select(bool isSelected)
446 {
447   DEBTRACE("SubjectObserver::select " << isSelected);
448   //propagate nothing
449 }
450 void SubjectObserver::update(GuiEvent event, int type, Subject* son)
451 {
452   DEBTRACE("SubjectObserver::update " << type << "," << eventName(event) << "," << son);
453   //propagate only RENAME events
454   if(event == RENAME)
455     _reference->update(event,type,son);
456 }
457
458 SubjectReference::SubjectReference(Subject* ref, Subject *parent)
459   : Subject(parent), _reference(ref)
460 {
461   _sobs=new SubjectObserver(this);
462   ref->attach(_sobs);
463 }
464
465 SubjectReference::~SubjectReference()
466 {
467   delete _sobs;
468 }
469
470 void SubjectReference::clean(Command *command)
471 {
472   if (_askRegisterUndo)
473     {
474       _askRegisterUndo = false;
475       registerUndoDestroy();
476     }
477   localclean(command);
478   Subject::clean(command);
479 }
480
481 void SubjectReference::localclean(Command *command)
482 {
483   DEBTRACE("SubjectReference::localClean ");
484 }
485
486 std::string SubjectReference::getName()
487 {
488   std::stringstream name;
489   name << "ref-->" << _reference->getName();
490   return name.str();
491 }
492
493 Subject* SubjectReference::getReference() const
494 {
495   return _reference;
496 }
497
498 void SubjectReference::reparent(Subject *parent)
499 {
500   _parent = parent;
501 }
502
503 // ----------------------------------------------------------------------------
504
505 SubjectNode::SubjectNode(YACS::ENGINE::Node *node, Subject *parent)
506   : Subject(parent), _node(node)
507 {
508   _listSubjectInputPort.clear();
509   _listSubjectOutputPort.clear();
510   _listSubjectIDSPort.clear();
511   _listSubjectODSPort.clear();
512   _listSubjectLink.clear();
513   _listSubjectControlLink.clear();
514   _execState = YACS::UNDEFINED;
515   Dispatcher* d=Dispatcher::getDispatcher();
516   d->addObserver(this,node,"status");
517 }
518
519 /*!
520  * all destruction is done in generic class SubjectNode
521  */
522 SubjectNode::~SubjectNode()
523 {
524   DEBTRACE("SubjectNode::~SubjectNode " << getName());
525   Dispatcher::getDispatcher()->removeObserver(this,_node,"status");
526
527   ComposedNode* father = _node->getFather();
528   GuiContext::getCurrent()->_mapOfSubjectNode.erase(_node);
529   if (father)
530     try
531       {
532         // Remove child except if it's the splitter node of a ForEachLoop
533         if (dynamic_cast<ForEachLoop*>(father) == NULL ||
534             getName() != ForEachLoop::NAME_OF_SPLITTERNODE)
535           {
536             father->edRemoveChild(_node);
537           }
538       }
539     catch (YACS::Exception &e)
540       {
541         DEBTRACE("------------------------------------------------------------------------------");
542         DEBTRACE("SubjectNode::localClean: father->edRemoveChild: YACS exception " << e.what());
543         DEBTRACE("------------------------------------------------------------------------------");
544       }
545 }
546
547 void SubjectNode::clean(Command *command)
548 {
549   if (_askRegisterUndo)
550     {
551       _askRegisterUndo = false;
552       registerUndoDestroy();
553     }
554   localclean(command);
555   Subject::clean(command);
556 }
557
558 void SubjectNode::localclean(Command *command)
559 {
560   DEBTRACE("SubjectNode::localClean ");
561   removeExternalLinks();
562   {
563     list<SubjectLink*>::iterator its;
564     list<SubjectLink*> cpll = _listSubjectLink;
565     for (its = cpll.begin(); its != cpll.end(); ++its)
566       erase(*its);
567   }
568   {
569     list<SubjectControlLink*>::iterator its;
570     list<SubjectControlLink*> cplcl = _listSubjectControlLink;
571     for (its = cplcl.begin(); its != cplcl.end(); ++its)
572       erase(*its);
573   }
574   {
575     list<SubjectInputPort*>::iterator iti;
576     list<SubjectInputPort*> cpli = _listSubjectInputPort;
577     for(iti = cpli.begin(); iti != cpli.end(); ++iti)
578       erase(*iti);
579   }
580   {
581     list<SubjectOutputPort*>::iterator ito;
582     list<SubjectOutputPort*> cplo = _listSubjectOutputPort;
583     for(ito = cplo.begin(); ito != cplo.end(); ++ito)
584       erase(*ito);
585   }
586   {
587     list<SubjectInputDataStreamPort*>::iterator itid;
588     list<SubjectInputDataStreamPort*> cplid = _listSubjectIDSPort;
589     for(itid = cplid.begin(); itid != cplid.end(); ++itid)
590       erase(*itid);
591   }
592   {
593     list<SubjectOutputDataStreamPort*>::iterator itod;
594     list<SubjectOutputDataStreamPort*> cplod = _listSubjectODSPort;
595     for(itod = cplod.begin(); itod != cplod.end(); ++itod)
596       erase(*itod);
597   }
598   if (_parent)
599     {
600       if( SubjectBloc* sb = dynamic_cast<SubjectBloc*>(_parent) )
601         sb->removeNode(this);
602       else if( SubjectForLoop* sfl = dynamic_cast<SubjectForLoop*>(_parent) )
603         sfl->completeChildrenSubjectList( 0 );
604       else if( SubjectWhileLoop* swl = dynamic_cast<SubjectWhileLoop*>(_parent) )
605         swl->completeChildrenSubjectList( 0 );
606       else if( SubjectDynParaLoop* sdpl = dynamic_cast<SubjectDynParaLoop*>(_parent) )
607         sdpl->removeNode(this);
608       else if( SubjectSwitch* ss = dynamic_cast<SubjectSwitch*>(_parent) )
609         ss->removeNode(this);
610     }
611 }
612
613 void SubjectNode::registerUndoDestroy()
614 {
615   DEBTRACE("SubjectNode::registerUndoDestroy " << getName());
616
617   Proc *undoProc = GuiContext::getCurrent()->getInvoc()->getUndoProc();
618   ComposedNode *oldFather = _node->getFather();
619
620   // --- clone the node in undoProc
621
622   ostringstream blocName;
623   blocName << "undoBloc_" << Invocator::_ctr++;
624   Bloc *undoBloc = new Bloc(blocName.str());
625   undoProc->edAddChild(undoBloc);
626   ComposedNode *newFather = undoBloc;
627   Node *clone = _node->cloneWithoutCompAndContDeepCpy(0);
628   newFather->edAddChild(clone);
629
630   // --- register a CommandCopyNode from undoProc
631
632   Proc *proc = GuiContext::getCurrent()->getProc();
633   string position = proc->getName();
634   if (proc != dynamic_cast<Proc*>(_node->getFather())) position = proc->getChildName(_node->getFather());
635
636   int swCase=0;
637   if (Switch* aswitch = dynamic_cast<Switch*>(_node->getFather()))
638     {
639       //the node is in a switch, save the case
640       swCase=aswitch->getRankOfNode(_node);
641     }
642
643   CommandCopyNode *command = new CommandCopyNode(undoProc,
644                                                  undoProc->getChildName(clone),
645                                                  position, swCase);
646   GuiContext::getCurrent()->getInvoc()->add(command);
647
648   // --- identify all the children service node
649
650   list<ServiceNode*> serviceList;
651   serviceList.clear();
652   ServiceNode *service = 0;
653   ComposedNode *cnode = 0;
654   if (service = dynamic_cast<ServiceNode*>(_node))
655     serviceList.push_back(service);
656   else
657     cnode = dynamic_cast<ComposedNode*>(_node);
658   if (cnode)
659     {
660       list<Node*> children = cnode->getAllRecursiveNodes();
661       list<Node*>::iterator it = children.begin();
662       for (; it != children.end(); ++it)
663         if (service = dynamic_cast<ServiceNode*>(*it))
664           serviceList.push_back(service);
665     }
666
667   // --- for all the children service node, find the componentInstance,
668   //     see if the componentInstance has other services that will stay alive after the destroy
669   //     if not, register a CommandAddComponentInstance
670   //
671
672   list<ServiceNode*>::const_iterator ita = serviceList.begin();
673   for (; ita != serviceList.end(); ++ita)
674     {
675       bool instanceUsedOutside = false;
676       service = *ita;  
677       ComponentInstance *compo = service->getComponent();
678       if (!compo) break;
679       YASSERT(GuiContext::getCurrent()->_mapOfSubjectComponent.count(compo));
680       SubjectComponent *scomp = GuiContext::getCurrent()->_mapOfSubjectComponent[compo];
681       //list<ServiceNode*> compServiceSet; 
682       set<SubjectServiceNode*>::const_iterator itset = scomp->_subServiceSet.begin();
683       for (; itset != scomp->_subServiceSet.end(); ++itset)
684         {
685           ServiceNode *sn = dynamic_cast<ServiceNode*>((*itset)->getNode());
686           if (sn && (sn != service))
687             {
688               //compServiceSet.push_back(sn);
689               instanceUsedOutside = true;
690               list<ServiceNode*>::const_iterator itb = serviceList.begin();
691               for (; itb != serviceList.end(); ++itb)
692                 {
693                   if ((*itb) == sn)
694                     {
695                       instanceUsedOutside = false;
696                       break;
697                     }
698                 }
699               if (instanceUsedOutside)
700                 break;
701             }
702         }
703
704       string instanceName = compo->getInstanceName();
705       if (!instanceUsedOutside)
706         {
707           string compoName = compo->getCompoName();
708           string containerName = compo->getContainer()->getName();
709           CommandAddComponentInstance *comaci = new CommandAddComponentInstance(compoName, containerName, instanceName);
710           GuiContext::getCurrent()->getInvoc()->add(comaci);
711         }
712        
713       string servicePos = proc->getChildName(service);
714       CommandAssociateServiceToComponent *comastc = new CommandAssociateServiceToComponent(servicePos,
715                                                                                            instanceName);
716       GuiContext::getCurrent()->getInvoc()->add(comastc);
717     }
718
719   // --- explore all the external links and register commands for recreation
720
721   vector<pair<OutPort *, InPort *> > listLeaving  = getNode()->getSetOfLinksLeavingCurrentScope();
722   vector<pair<InPort *, OutPort *> > listIncoming = getNode()->getSetOfLinksComingInCurrentScope();
723   vector<pair<OutPort *, InPort *> > globalList = listLeaving;
724   vector<pair<InPort *, OutPort *> >::iterator it1;
725   for (it1 = listIncoming.begin(); it1 != listIncoming.end(); ++it1)
726     {
727       pair<OutPort *, InPort *> outin = pair<OutPort *, InPort *>((*it1).second, (*it1).first);
728       globalList.push_back(outin);
729     }
730   vector<pair<OutPort *, InPort *> >::iterator it2;
731   for (it2 = globalList.begin(); it2 != globalList.end(); ++it2)
732     {
733       SubjectLink* subject = 0;
734       if (GuiContext::getCurrent()->_mapOfSubjectLink.count(*it2))
735         {
736           subject = GuiContext::getCurrent()->_mapOfSubjectLink[*it2];
737           YASSERT(subject);
738           DEBTRACE("register undo destroy link " << subject->getName());
739           subject->registerUndoDestroy();
740         }
741     }
742
743   // --- explore all the external control links and register commands for recreation
744
745   list<SubjectControlLink*> cplcl = getSubjectControlLinks();
746   list<SubjectControlLink*>::iterator its;
747   Node* node = getNode();
748   for (its = cplcl.begin(); its != cplcl.end(); ++its)
749     {
750       bool inside = true;
751       Node *nout = (*its)->getSubjectOutNode()->getNode();
752       Node *nin = (*its)->getSubjectInNode()->getNode();
753       inside = inside && (node == nout);
754       inside = inside && (node == nin);
755       if (!inside)
756         {
757           (*its)->registerUndoDestroy();
758         }
759     }
760 }
761
762 bool SubjectNode::reparent(Subject* parent)
763 {
764   DEBTRACE("SubjectNode::reparent");
765   Subject *sub = getParent(); // --- old parent subject
766   SubjectComposedNode *sop = dynamic_cast<SubjectComposedNode*>(sub);
767   YASSERT(sop);
768   SubjectComposedNode *snp = dynamic_cast<SubjectComposedNode*>(parent); // --- new parent subject
769   if (!snp)
770     {
771       GuiContext::getCurrent()->_lastErrorMessage = "new parent must be a composed node";
772       DEBTRACE(GuiContext::getCurrent()->_lastErrorMessage);
773       return false;
774     }
775   ComposedNode *cnp = dynamic_cast<ComposedNode*>(snp->getNode());
776   YASSERT(cnp);
777   Proc *proc = GuiContext::getCurrent()->getProc();
778   Proc *fromproc=_node->getProc();
779   if(proc != fromproc)
780     {
781       GuiContext::getCurrent()->_lastErrorMessage = "cut is not yet possible across procs";
782       DEBTRACE(GuiContext::getCurrent()->_lastErrorMessage);
783       return false;
784     }
785
786   string position = "";
787   if (proc != dynamic_cast<Proc*>(_node))
788     position = proc->getChildName(_node);
789   else
790     position = _node->getName();
791
792   string newParent = "";
793   if (proc != dynamic_cast<Proc*>(cnp))
794     newParent = proc->getChildName(cnp);
795   else
796     newParent = cnp->getName();
797
798   CommandReparentNode *command = new CommandReparentNode(position, newParent);
799   if (command->execute())
800     {
801       GuiContext::getCurrent()->getInvoc()->add(command);
802       return true;
803     }
804   else delete command;
805   DEBTRACE(GuiContext::getCurrent()->_lastErrorMessage);
806   return false;
807 }
808
809 void SubjectNode::recursiveUpdate(GuiEvent event, int type, Subject* son)
810 {
811   update(event, type, son);
812 }
813
814 bool SubjectNode::copy(Subject* parent)
815 {
816   DEBTRACE("SubjectNode::copy");
817   Subject *sop = getParent(); // --- old parent subject
818   SubjectComposedNode *snp = dynamic_cast<SubjectComposedNode*>(parent); // --- new parent subject
819   if (!snp)
820     {
821       GuiContext::getCurrent()->_lastErrorMessage = "new parent must be a composed node";
822       DEBTRACE(GuiContext::getCurrent()->_lastErrorMessage);
823       return false;
824     }
825   ComposedNode *cnp = dynamic_cast<ComposedNode*>(snp->getNode());
826   YASSERT(cnp);
827   Proc *proc = GuiContext::getCurrent()->getProc();
828   Proc *fromproc=_node->getProc();
829   if(proc != fromproc)
830     {
831       GuiContext::getCurrent()->_lastErrorMessage = "It is not possible to paste an object from one schema to another.";
832       DEBTRACE(GuiContext::getCurrent()->_lastErrorMessage);
833       return false;
834     }
835
836   string position = "";
837   if (fromproc != dynamic_cast<Proc*>(_node))
838     position = fromproc->getChildName(_node);
839   else
840     position = _node->getName();
841
842   string newParent = "";
843   if (proc != dynamic_cast<Proc*>(cnp))
844     newParent = proc->getChildName(cnp);
845   else
846     newParent = cnp->getName();
847
848   CommandCopyNode *command = new CommandCopyNode(fromproc, position, newParent);
849   if (command->execute())
850     {
851       GuiContext::getCurrent()->getInvoc()->add(command);
852       return true;
853     }
854   else delete command;
855   DEBTRACE(GuiContext::getCurrent()->_lastErrorMessage);
856   return false;
857
858 }
859
860 std::string SubjectNode::getName()
861 {
862   return _node->getName();
863 }
864
865 YACS::ENGINE::Node* SubjectNode::getNode()
866 {
867   return _node;
868 }
869
870 int SubjectNode::isValid()
871 {
872   return _node->isValid();
873 }
874
875 bool SubjectNode::setName(std::string name)
876 {
877   DEBTRACE("SubjectNode::setName " << name);
878   Proc *proc = GuiContext::getCurrent()->getProc();
879   string position = "";
880   if (proc != dynamic_cast<Proc*>(_node))
881     position = proc->getChildName(_node);
882   else
883     position = _node->getName();
884   CommandRenameNode* command = new CommandRenameNode(position, name);
885   if (command->execute())
886     {
887       GuiContext::getCurrent()->getInvoc()->add(command);
888       return true;
889     }
890   else delete command;
891   return false;
892 }
893
894 void SubjectNode::notifyObserver(Node* object,const std::string& event)
895 {
896   DEBTRACE("SubjectNode::notifyObserver " << object->getName() << " " << event);
897   TypeOfElem ntyp = ProcInvoc::getTypeOfNode(object);
898   update(UPDATE, ntyp , 0 );
899 }
900
901 void SubjectNode::saveLinks()
902 {
903   DEBTRACE("SubjectNode::saveLinks");
904   loutgate= _node->getInGate()->getBackLinks();
905   singate= _node->getOutGate()->edSetInGate();
906   std::list<OutGate *>::const_iterator ito;
907   for(ito=loutgate.begin();ito != loutgate.end();ito++)
908     {
909       Node* n1=(*ito)->getNode();
910       Node* n2=_node;
911       DEBTRACE(n1->getName()<< " " << n2->getName());
912     }
913   std::list<InGate *>::const_iterator iti;
914   for(iti=singate.begin();iti != singate.end();iti++)
915     {
916       Node* n1=_node;
917       Node* n2=(*iti)->getNode();
918       DEBTRACE(n1->getName()<< " " << n2->getName());
919     }
920
921   dataLinks.clear();
922   dataflowLinks.clear();
923
924   std::vector< std::pair<OutPort *, InPort *> > listLeaving  = getNode()->getSetOfLinksLeavingCurrentScope();
925   std::vector< std::pair<OutPort *, InPort *> >::iterator it3;
926   for (it3 = listLeaving.begin(); it3 != listLeaving.end(); ++it3)
927     {
928       OutPort* p1=(*it3).first;
929       InPort* p2=(*it3).second;
930       Node* n1=p1->getNode();
931       Node* n2=p2->getNode();
932       //are nodes in sequence (control link direct or indirect) ?
933       ComposedNode* fath= ComposedNode::getLowestCommonAncestor(n1,n2);
934       if(n1 == fath ||n2 == fath)
935         {
936           //consider it as a data only link
937           DEBTRACE("It's a data link: " << n1->getName() << "." << p1->getName() << " -> "<< n2->getName() << "." << p2->getName());
938           dataLinks.push_back(std::pair<OutPort *, InPort *>(p1,p2));
939           continue;
940         }
941       while(n1->getFather() != fath) n1=n1->getFather();
942       while(n2->getFather() != fath) n2=n2->getFather();
943       OutGate* outg=n1->getOutGate();
944       if(!outg->isAlreadyInSet(n2->getInGate()))
945         {
946           DEBTRACE("It's a data link: "<<p1->getNode()->getName()<<"."<<p1->getName()<<" -> "<< p2->getNode()->getName()<<"."<<p2->getName());
947           dataLinks.push_back(std::pair<OutPort *, InPort *>(p1,p2));
948         }
949       else
950         {
951           DEBTRACE("It's a dataflow link: "<<p1->getNode()->getName()<<"."<<p1->getName()<<" -> "<< p2->getNode()->getName()<<"."<<p2->getName());
952           dataflowLinks.push_back(std::pair<OutPort *, InPort *>(p1,p2));
953         }
954     }
955
956   std::vector< std::pair<InPort *, OutPort *> > listIncoming  = getNode()->getSetOfLinksComingInCurrentScope();
957   std::vector< std::pair<InPort *, OutPort *> >::iterator it4;
958   for (it4 = listIncoming.begin(); it4 != listIncoming.end(); ++it4)
959     {
960       OutPort* p1=(*it4).second;
961       InPort* p2=(*it4).first;
962       Node* n1=p1->getNode();
963       Node* n2=p2->getNode();
964       //are nodes in sequence (control link direct or indirect) ?
965       ComposedNode* fath= ComposedNode::getLowestCommonAncestor(n1,n2);
966       if(n1 == fath ||n2 == fath)
967         {
968           //consider it as a data only link
969           DEBTRACE("It's a data link: " << n1->getName() << "." << p1->getName() << " -> "<< n2->getName() << "." << p2->getName());
970           dataLinks.push_back(std::pair<OutPort *, InPort *>(p1,p2));
971           continue;
972         }
973       while(n1->getFather() != fath) n1=n1->getFather();
974       while(n2->getFather() != fath) n2=n2->getFather();
975       OutGate* outg=n1->getOutGate();
976       if(!outg->isAlreadyInSet(n2->getInGate()))
977         {
978           DEBTRACE("It's a data link: "<<p1->getNode()->getName()<<"."<<p1->getName()<<" -> "<< p2->getNode()->getName()<<"."<<p2->getName());
979           dataLinks.push_back(std::pair<OutPort *, InPort *>(p1,p2));
980         }
981       else
982         {
983           DEBTRACE("It's a dataflow link: "<<p1->getNode()->getName()<<"."<<p1->getName()<<" -> "<< p2->getNode()->getName()<<"."<<p2->getName());
984           dataflowLinks.push_back(std::pair<OutPort *, InPort *>(p1,p2));
985         }
986     }
987 }
988
989 void SubjectNode::restoreLinks()
990 {
991   DEBTRACE("SubjectNode::restoreLinks");
992   //restore simple data links
993   std::vector< std::pair<OutPort *, InPort *> >::iterator it3;
994   for (it3 = dataLinks.begin(); it3 != dataLinks.end(); ++it3)
995     {
996       OutPort* p1=(*it3).first;
997       InPort* p2=(*it3).second;
998       Node* n1=p1->getNode();
999       Node* n2=p2->getNode();
1000       ComposedNode* fath= ComposedNode::getLowestCommonAncestor(n1,n2);
1001       try
1002         {
1003           fath->edAddLink(p1,p2);
1004         }
1005       catch(Exception& ex)
1006         {
1007           // if a link can't be restored ignore it. It's possible when a node is reparented to a foreachloop 
1008           continue;
1009         }
1010       SubjectComposedNode *scla = dynamic_cast<SubjectComposedNode*>(GuiContext::getCurrent()->_mapOfSubjectNode[fath]);
1011       SubjectNode *sno = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(n1)];
1012       SubjectNode *sni = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(n2)];
1013       SubjectDataPort *spo = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(p1)];
1014       SubjectDataPort *spi = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(p2)];
1015       scla->addSubjectLink(sno,spo,sni,spi);
1016     }
1017   //restore dataflow links
1018   for (it3 = dataflowLinks.begin(); it3 != dataflowLinks.end(); ++it3)
1019     {
1020       OutPort* p1=(*it3).first;
1021       InPort* p2=(*it3).second;
1022       Node* n1=p1->getNode();
1023       Node* n2=p2->getNode();
1024       ComposedNode* fath= ComposedNode::getLowestCommonAncestor(n1,n2);
1025       try
1026         {
1027           fath->edAddDFLink(p1,p2);
1028         }
1029       catch(Exception& ex)
1030         {
1031           // if a link can't be restored ignore it. It's possible when a node is reparented to a foreachloop 
1032           continue;
1033         }
1034       SubjectComposedNode *scla = dynamic_cast<SubjectComposedNode*>(GuiContext::getCurrent()->_mapOfSubjectNode[fath]);
1035       SubjectNode *sno = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(n1)];
1036       SubjectNode *sni = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(n2)];
1037       SubjectDataPort *spo = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(p1)];
1038       SubjectDataPort *spi = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(p2)];
1039       scla->addSubjectLink(sno,spo,sni,spi);
1040       if(n1==fath || n2==fath) continue;
1041       while(n1->getFather() != fath) n1=n1->getFather();
1042       while(n2->getFather() != fath) n2=n2->getFather();
1043       OutGate *ogate = n1->getOutGate();
1044       InGate *igate = n2->getInGate();
1045       if (ogate->isAlreadyInSet(igate))
1046         {
1047           pair<Node*,Node*> keyLink(n1,n2);
1048           if (!GuiContext::getCurrent()->_mapOfSubjectControlLink.count(keyLink))
1049             {
1050               SubjectNode *sfno = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(n1)];
1051               SubjectNode *sfni = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(n2)];
1052               scla->addSubjectControlLink(sfno, sfni);
1053             }
1054         }
1055     }
1056
1057   //reconnect control links
1058   // links from another node to this node
1059   std::list<OutGate *>::const_iterator it;
1060   for(it=loutgate.begin();it != loutgate.end();it++)
1061     {
1062       Node* n1=(*it)->getNode();
1063       Node* n2=_node;
1064       if(GuiContext::getCurrent()->_mapOfSubjectNode.count(n1)==0)
1065         {
1066           //It's an internal node or a destroyed one : don't treat it
1067           continue;
1068         }
1069       ComposedNode* fath= ComposedNode::getLowestCommonAncestor(n1,n2);
1070       if(n1 == fath)continue;
1071       if(n2 == fath)continue;
1072       //add a control link only if nodes are not in the same descendance
1073       while(n1->getFather() != fath) n1=n1->getFather();
1074       while(n2->getFather() != fath) n2=n2->getFather();
1075       OutGate *ogate = n1->getOutGate();
1076       InGate *igate = n2->getInGate();
1077       if (!ogate->isAlreadyInSet(igate))
1078         {
1079           fath->edAddCFLink(n1,n2);
1080           SubjectComposedNode *scla = dynamic_cast<SubjectComposedNode*>(GuiContext::getCurrent()->_mapOfSubjectNode[fath]);
1081           SubjectNode * subOutNode = GuiContext::getCurrent()->_mapOfSubjectNode[n1];
1082           SubjectNode * subInNode = GuiContext::getCurrent()->_mapOfSubjectNode[n2];
1083           scla->addSubjectControlLink(subOutNode,subInNode);
1084         }
1085     }
1086
1087   std::list<InGate *>::const_iterator it2;
1088   for(it2=singate.begin();it2 != singate.end();it2++)
1089     {
1090       Node* n1=_node;
1091       Node* n2=(*it2)->getNode();
1092       if(GuiContext::getCurrent()->_mapOfSubjectNode.count(n2)==0)
1093         {
1094           //It's an internal node or a destroyed one : don't treat it
1095           continue;
1096         }
1097       ComposedNode* fath= ComposedNode::getLowestCommonAncestor(n1,n2);
1098       if(n1 == fath)continue;
1099       if(n2 == fath)continue;
1100       //add a control link only if nodes are not in the same descendance
1101       while(n1->getFather() != fath) n1=n1->getFather();
1102       while(n2->getFather() != fath) n2=n2->getFather();
1103       OutGate *ogate = n1->getOutGate();
1104       InGate *igate = n2->getInGate();
1105       if (!ogate->isAlreadyInSet(igate))
1106         {
1107           fath->edAddCFLink(n1,n2);
1108           SubjectComposedNode *scla = dynamic_cast<SubjectComposedNode*>(GuiContext::getCurrent()->_mapOfSubjectNode[fath]);
1109           SubjectNode * subOutNode = GuiContext::getCurrent()->_mapOfSubjectNode[n1];
1110           SubjectNode * subInNode = GuiContext::getCurrent()->_mapOfSubjectNode[n2];
1111           scla->addSubjectControlLink(subOutNode,subInNode);
1112         }
1113     }
1114 }
1115
1116 bool SubjectNode::putInComposedNode(std::string name,std::string type, bool toSaveRestoreLinks)
1117 {
1118   Proc *proc = GuiContext::getCurrent()->getProc();
1119   string position = "";
1120   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
1121
1122   CommandPutInComposedNode *command = new CommandPutInComposedNode(position, name, type, toSaveRestoreLinks);
1123   if (command->execute())
1124     {
1125       GuiContext::getCurrent()->getInvoc()->add(command);
1126       return true;
1127     }
1128   else delete command;
1129   DEBTRACE(GuiContext::getCurrent()->_lastErrorMessage);
1130   return false;
1131 }
1132
1133 SubjectInputPort* SubjectNode::addSubjectInputPort(YACS::ENGINE::InputPort *port,
1134                                                    std::string name)
1135 {
1136   string theName = name;
1137   if (name.empty()) theName =port->getName();
1138   DEBTRACE("SubjectNode::addSubjectInputPort "<< theName);
1139   SubjectInputPort *son = new SubjectInputPort(port, this);
1140   GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(port)] = son;
1141   _listSubjectInputPort.push_back(son);
1142   if (!name.empty()) son->setName(name);
1143   update(ADD, INPUTPORT ,son);
1144   YACS::ENGINE::TypeCode *typcod = port->edGetType();
1145   if (!GuiContext::getCurrent()->getSubjectProc()->addComSubjectDataType(typcod, typcod->name()))
1146     GuiContext::getCurrent()->getSubjectProc()->addSubjectDataType(typcod, typcod->name());  // --- new type of forEachLoop
1147   return son;
1148 }
1149
1150 void SubjectNode::update( GuiEvent event, int type, Subject* son )
1151 {
1152   Subject::update( event, type, son );
1153   
1154   // remove subject data type if necessary
1155   YACS::HMI::SubjectDataPort* aSPort = dynamic_cast< YACS::HMI::SubjectDataPort* >( son );
1156 //   if ( aSPort && event == REMOVE )
1157 //   {
1158 //     YACS::ENGINE::DataPort* aEPort = aSPort->getPort();
1159 //     if ( aEPort )
1160 //     {
1161 //       YACS::ENGINE::TypeCode* aTypeCode = aEPort->edGetType();
1162 //       if ( aTypeCode )
1163 //         GuiContext::getCurrent()->getSubjectProc()->removeSubjectDataType( aTypeCode );
1164 //     }
1165 //   }
1166 }
1167
1168 void SubjectNode::setExecState(int execState)
1169 {
1170   _execState = execState;
1171   update(YACS::HMI::UPDATEPROGRESS, _execState, this);
1172 }
1173
1174 SubjectOutputPort* SubjectNode::addSubjectOutputPort(YACS::ENGINE::OutputPort *port,
1175                                                      std::string name)
1176 {
1177   string theName = name;
1178   if (name.empty()) theName =port->getName();
1179   DEBTRACE("SubjectNode::addSubjectOutputPort "<< theName);
1180   SubjectOutputPort *son = new SubjectOutputPort(port, this);
1181   GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(port)] = son;
1182   _listSubjectOutputPort.push_back(son);
1183   if (!name.empty()) son->setName(name);
1184   update(ADD, OUTPUTPORT ,son);
1185   YACS::ENGINE::TypeCode *typcod = port->edGetType();
1186   GuiContext::getCurrent()->getSubjectProc()->addComSubjectDataType(typcod, typcod->name());
1187   return son;
1188 }
1189
1190 SubjectInputDataStreamPort* SubjectNode::addSubjectIDSPort(YACS::ENGINE::InputDataStreamPort *port,
1191                                                            std::string name)
1192 {
1193   string theName = name;
1194   if (name.empty()) theName =port->getName();
1195   DEBTRACE("SubjectNode::addSubjectIDSPort "<< theName);
1196   SubjectInputDataStreamPort *son = new SubjectInputDataStreamPort(port, this);
1197   GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(port)] = son;
1198   _listSubjectIDSPort.push_back(son);
1199   if (!name.empty()) son->setName(name);
1200   update(ADD, INPUTDATASTREAMPORT ,son);
1201   YACS::ENGINE::TypeCode *typcod = port->edGetType();
1202   GuiContext::getCurrent()->getSubjectProc()->addComSubjectDataType(typcod, typcod->name());
1203   return son;
1204 }
1205
1206
1207 SubjectOutputDataStreamPort* SubjectNode::addSubjectODSPort(YACS::ENGINE::OutputDataStreamPort *port,
1208                                                             std::string name)
1209 {
1210   string theName = name;
1211   if (name.empty()) theName =port->getName();
1212   DEBTRACE("SubjectNode::addSubjectODSPort "<< theName);
1213   SubjectOutputDataStreamPort *son = new SubjectOutputDataStreamPort(port, this);
1214   GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(port)] = son;
1215   _listSubjectODSPort.push_back(son);
1216   if (!name.empty()) son->setName(name);
1217   update(ADD, OUTPUTDATASTREAMPORT ,son);
1218   YACS::ENGINE::TypeCode *typcod = port->edGetType();
1219   GuiContext::getCurrent()->getSubjectProc()->addComSubjectDataType(typcod, typcod->name());
1220   return son;
1221 }
1222
1223 bool SubjectNode::tryCreateLink(SubjectNode *subOutNode, SubjectNode *subInNode)
1224 {
1225   DEBTRACE("SubjectNode::tryCreateLink " << subOutNode->getName() << " " << subInNode->getName());
1226   Proc *proc = GuiContext::getCurrent()->getProc();
1227   Node *outNode = subOutNode->getNode();
1228   string outNodePos = proc->getChildName(outNode);
1229   Node *inNode = subInNode->getNode();
1230   string inNodePos = proc->getChildName(inNode);
1231   CommandAddControlLink *command = new CommandAddControlLink(outNodePos, inNodePos);
1232   if (command->execute())
1233     {
1234       GuiContext::getCurrent()->getInvoc()->add(command);
1235       return true;
1236     }
1237   else
1238     {
1239       delete command;
1240       return false;
1241     }
1242 }
1243
1244 void SubjectNode::removeExternalLinks()
1245 {
1246   DEBTRACE("SubjectNode::removeExternalLinks " << getName());
1247   std::vector< std::pair<OutPort *, InPort *> > listLeaving  = getNode()->getSetOfLinksLeavingCurrentScope();
1248   std::vector< std::pair<InPort *, OutPort *> > listIncoming = getNode()->getSetOfLinksComingInCurrentScope();
1249   std::vector< std::pair<OutPort *, InPort *> > globalList = listLeaving;
1250   std::vector< std::pair<InPort *, OutPort *> >::iterator it1;
1251   for (it1 = listIncoming.begin(); it1 != listIncoming.end(); ++it1)
1252     {
1253       std::pair<OutPort *, InPort *> outin = std::pair<OutPort *, InPort *>((*it1).second, (*it1).first);
1254       globalList.push_back(outin);
1255     }
1256   std::vector< std::pair<OutPort *, InPort *> >::iterator it2;
1257   for (it2 = globalList.begin(); it2 != globalList.end(); ++it2)
1258     {
1259       SubjectLink* subject = 0;
1260       if (GuiContext::getCurrent()->_mapOfSubjectLink.count(*it2))
1261         {
1262           subject = GuiContext::getCurrent()->_mapOfSubjectLink[*it2];
1263           YASSERT(subject);
1264           DEBTRACE("link to remove " << subject->getName());
1265           erase(subject);
1266           GuiContext::getCurrent()->_mapOfSubjectLink.erase(*it2);
1267         }
1268       else
1269         {
1270           DEBTRACE("------------------------------------------------------------------------------");
1271           DEBTRACE("SubjectNode::removeExternalLinks(): an external link not in map...");
1272           DEBTRACE("------------------------------------------------------------------------------");
1273         }
1274     } 
1275 }
1276
1277 void SubjectNode::removeExternalControlLinks()
1278 {
1279   DEBTRACE("SubjectNode::removeExternalControlLinks " << getName());
1280   list<SubjectControlLink*> cplcl = getSubjectControlLinks();
1281   list<SubjectControlLink*>::iterator its;
1282   Node* node = getNode();
1283   for (its = cplcl.begin(); its != cplcl.end(); ++its)
1284     {
1285       bool inside = true;
1286       Node *nout = (*its)->getSubjectOutNode()->getNode();
1287       Node *nin = (*its)->getSubjectInNode()->getNode();
1288       inside = inside && (node == nout);
1289       inside = inside && (node == nin);
1290       if (!inside)
1291         Subject::erase(*its);
1292     }
1293 }
1294
1295 std::map<std::string, std::string> SubjectNode::getProperties()
1296 {
1297   return _node->getPropertyMap();
1298 }
1299
1300 bool SubjectNode::setProperties(std::map<std::string, std::string> properties)
1301 {
1302   Proc *proc = GuiContext::getCurrent()->getProc();
1303   string position = "";
1304   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
1305
1306   CommandSetNodeProperties *command = new CommandSetNodeProperties(position, properties);
1307   if (command->execute())
1308     {
1309       GuiContext::getCurrent()->getInvoc()->add(command);
1310       return true;
1311     }
1312   else delete command;
1313   return false;
1314 }
1315
1316 // ----------------------------------------------------------------------------
1317
1318 SubjectComposedNode::SubjectComposedNode(YACS::ENGINE::ComposedNode *composedNode,
1319                                          Subject *parent)
1320   : SubjectNode(composedNode, parent), _composedNode(composedNode)
1321 {
1322 }
1323
1324 /*!
1325  * all generic destruction is done in generic class SubjectNode
1326  */
1327 SubjectComposedNode::~SubjectComposedNode()
1328 {
1329   DEBTRACE("SubjectComposedNode::~SubjectComposedNode " << getName());
1330 }
1331
1332 void SubjectComposedNode::clean(Command *command)
1333 {
1334   if (_askRegisterUndo)
1335     {
1336       _askRegisterUndo = false;
1337       registerUndoDestroy();
1338     }
1339   localclean(command);
1340   SubjectNode::clean(command);
1341 }
1342
1343 void SubjectComposedNode::localclean(Command *command)
1344 {
1345   DEBTRACE("SubjectComposedNode::localClean ");
1346 }
1347
1348 SubjectNode* SubjectComposedNode::addNode(YACS::ENGINE::Catalog *catalog,
1349                                           std::string compo,
1350                                           std::string type,
1351                                           std::string name,
1352                                           bool newCompoInst)
1353 {
1354   DEBTRACE("SubjectComposedNode::addNode("<<catalog<<","<<compo<<","<<type<<","<<name<<")");
1355   SubjectNode* body = 0;
1356   GuiContext::getCurrent()->_lastErrorMessage = "YACS Internal Error: SubjectComposedNode::addNode"; 
1357   return body;
1358 }
1359
1360 SubjectNode *SubjectComposedNode::createNode(YACS::ENGINE::Catalog *catalog,
1361                                              std::string compo,
1362                                              std::string type,
1363                                              std::string name,
1364                                              bool newCompoInst,
1365                                              int swCase)
1366 {
1367   Proc *proc = GuiContext::getCurrent()->getProc();
1368   string position = "";
1369   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
1370   CommandAddNodeFromCatalog *command = new CommandAddNodeFromCatalog(catalog,
1371                                                                      compo,
1372                                                                      type,
1373                                                                      position,
1374                                                                      name,
1375                                                                      newCompoInst,
1376                                                                      swCase);
1377   if (command->execute())
1378     {
1379       GuiContext::getCurrent()->getInvoc()->add(command);
1380       Node * node = command->getNode();
1381       return command->getSubjectNode();
1382     }
1383   else delete command;
1384   return 0;
1385 }
1386
1387 SubjectNode *SubjectComposedNode::addSubjectNode(YACS::ENGINE::Node * node,
1388                                                  std::string name,
1389                                                  YACS::ENGINE::Catalog *catalog,
1390                                                  std::string compo,
1391                                                  std::string type)
1392 {
1393   string theName = name;
1394   if (name.empty()) theName =node->getName();
1395   DEBTRACE("SubjectComposedNode::addSubjectNode "<< theName);
1396   TypeOfElem ntyp = ProcInvoc::getTypeOfNode(node);
1397   DEBTRACE("TypeOfNode: " << ntyp);
1398   SubjectNode *son = 0;
1399   switch(ntyp)
1400     {
1401     case BLOC:
1402       son = new SubjectBloc(dynamic_cast<YACS::ENGINE::Bloc*>(node), this);
1403       break;
1404     case PYTHONNODE:
1405       son = new SubjectPythonNode(dynamic_cast<YACS::ENGINE::PythonNode*>(node), this);
1406       break;
1407     case PYFUNCNODE:
1408       son = new SubjectPyFuncNode(dynamic_cast<YACS::ENGINE::PyFuncNode*>(node), this);
1409       break;
1410     case CORBANODE:
1411       son = new SubjectCORBANode(dynamic_cast<YACS::ENGINE::CORBANode*>(node), this);
1412       break;
1413     case CPPNODE:
1414       son = new SubjectCppNode(dynamic_cast<YACS::ENGINE::CppNode*>(node), this);
1415       break;
1416     case SALOMENODE:
1417       son = new SubjectSalomeNode(dynamic_cast<YACS::ENGINE::SalomeNode*>(node), this);
1418       break;
1419     case SALOMEPYTHONNODE:
1420       son = new SubjectSalomePythonNode(dynamic_cast<YACS::ENGINE::SalomePythonNode*>(node), this);
1421       break;
1422     case XMLNODE:
1423       son = new SubjectXmlNode(dynamic_cast<YACS::ENGINE::XmlNode*>(node), this);
1424       break;
1425     case SPLITTERNODE:
1426       son = new SubjectSplitterNode(dynamic_cast<YACS::ENGINE::SplitterNode*>(node), this);
1427       break;
1428     case PRESETNODE:
1429       son = new SubjectPresetNode(dynamic_cast<YACS::ENGINE::PresetNode*>(node), this);
1430       break;
1431     case OUTNODE:
1432       son = new SubjectOutNode(dynamic_cast<YACS::ENGINE::OutNode*>(node), this);
1433       break;
1434     case STUDYINNODE:
1435       son = new SubjectStudyInNode(dynamic_cast<YACS::ENGINE::StudyInNode*>(node), this);
1436       break;
1437     case STUDYOUTNODE:
1438       son = new SubjectStudyOutNode(dynamic_cast<YACS::ENGINE::StudyOutNode*>(node), this);
1439       break;
1440     case FORLOOP:
1441       son = new SubjectForLoop(dynamic_cast<YACS::ENGINE::ForLoop*>(node), this);
1442       break;
1443     case WHILELOOP:
1444       son = new SubjectWhileLoop(dynamic_cast<YACS::ENGINE::WhileLoop*>(node), this);
1445       break;
1446     case SWITCH:
1447       son = new SubjectSwitch(dynamic_cast<YACS::ENGINE::Switch*>(node), this);
1448       break;
1449     case FOREACHLOOP:
1450       son = new SubjectForEachLoop(dynamic_cast<YACS::ENGINE::ForEachLoop*>(node), this);
1451       break;
1452     case OPTIMIZERLOOP:
1453       son = new SubjectOptimizerLoop(dynamic_cast<YACS::ENGINE::OptimizerLoop*>(node), this);
1454       break;
1455     default:
1456       throw YACS::Exception("Not implemented");
1457       //YASSERT(0);
1458     }
1459   YASSERT(son);
1460   GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(node)] = son;
1461   GuiContext::getCurrent()->_mapOfExecSubjectNode[node->getNumId()] = son;
1462   if (!name.empty()) son->setName(name);
1463   completeChildrenSubjectList(son);
1464   update(ADD, ntyp ,son);
1465   if (SubjectServiceNode *service = dynamic_cast<SubjectServiceNode*>(son))
1466     if (catalog && !compo.empty() && !type.empty()) // --- clone from catalog: set component
1467       service->setComponentFromCatalog(catalog,compo,type);
1468     else
1469       service->setComponent();
1470   return son;
1471 }
1472
1473 void SubjectComposedNode::completeChildrenSubjectList(SubjectNode *son)
1474 {
1475 }
1476
1477 void SubjectComposedNode::loadChildren()
1478 {
1479   list<Node *> setOfNode= _composedNode->edGetDirectDescendants();
1480   if (ForEachLoop *feloop = dynamic_cast<ForEachLoop*>(_composedNode))
1481     {
1482       Node *node2Insert=feloop->getChildByName(ForEachLoop::NAME_OF_SPLITTERNODE);
1483       if(find(setOfNode.begin(),setOfNode.end(),node2Insert)==setOfNode.end())
1484         setOfNode.push_back(node2Insert);
1485     }
1486   for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1487     {
1488       try
1489         {
1490           SubjectNode * son = addSubjectNode(*iter);
1491           son->loadChildren();
1492         }
1493       catch(YACS::Exception& ex)
1494         {
1495           std::cerr << "Unknown type of node" << std::endl;
1496         }
1497     }
1498   list<InputPort*>  listInputPorts  = _composedNode->getLocalInputPorts();
1499   list<OutputPort*> listOutputPorts = _composedNode->getLocalOutputPorts();
1500   list<InputDataStreamPort*>  listIDSPorts = _composedNode->getSetOfInputDataStreamPort();
1501   list<OutputDataStreamPort*> listODSPorts = _composedNode->getSetOfOutputDataStreamPort();
1502   list<InputPort*>::const_iterator iti;
1503   for (iti = listInputPorts.begin(); iti != listInputPorts.end(); ++iti)
1504     addSubjectInputPort(*iti);
1505   list<OutputPort*>::const_iterator ito;
1506   for (ito = listOutputPorts.begin(); ito != listOutputPorts.end(); ++ito)
1507     addSubjectOutputPort(*ito);
1508 }
1509
1510 SubjectLink* SubjectComposedNode::addSubjectLink(SubjectNode *sno,
1511                                                  SubjectDataPort *spo,
1512                                                  SubjectNode *sni,
1513                                                  SubjectDataPort *spi)
1514 {
1515   DEBTRACE("SubjectComposedNode::addSubjectLink");
1516   OutPort *outp = dynamic_cast<OutPort*>(spo->getPort());
1517   InPort *inp = dynamic_cast<InPort*>(spi->getPort());
1518   pair<OutPort*,InPort*> keyLink(outp,inp);
1519   //Don't create a new subject if it already exists
1520   if(GuiContext::getCurrent()->_mapOfSubjectLink.count(keyLink)!=0)
1521     return GuiContext::getCurrent()->_mapOfSubjectLink[keyLink];
1522
1523   SubjectLink *son = new SubjectLink(sno, spo, sni, spi, this);
1524   GuiContext::getCurrent()->_mapOfSubjectLink[keyLink] = son;
1525   _listSubjectLink.push_back(son);
1526   spo->addSubjectLink(son);
1527   spi->addSubjectLink(son);
1528   update(ADDLINK, DATALINK, son);
1529   spi->update(UPDATE, DATALINK, spo);
1530   spo->update(UPDATE, DATALINK, spi);
1531   DEBTRACE("addSubjectLink: " << getName() << " " << son->getName());
1532   return son;
1533 }
1534
1535 void SubjectComposedNode::removeLink(SubjectLink* link)
1536 {
1537   DEBTRACE("removeLink: " << link->getName());
1538
1539   OutPort *outp = dynamic_cast<OutPort*>(link->getSubjectOutPort()->getPort());
1540   InPort  *inp  = dynamic_cast<InPort*>(link->getSubjectInPort()->getPort());
1541   pair<OutPort*,InPort*> keyLink(outp,inp);
1542   if (GuiContext::getCurrent()->_mapOfSubjectLink.count(keyLink))
1543     {
1544       DEBTRACE(outp->getName() << " " << inp->getName());
1545       GuiContext::getCurrent()->_mapOfSubjectLink.erase(keyLink);
1546     }
1547
1548   link->getSubjectOutPort()->removeSubjectLink(link);
1549   link->getSubjectInPort()->removeSubjectLink(link);
1550   _listSubjectLink.remove(link);
1551 }
1552
1553 SubjectControlLink* SubjectComposedNode::addSubjectControlLink(SubjectNode *sno,
1554                                                         SubjectNode *sni)
1555 {
1556   Node *outn = sno->getNode();
1557   Node *inn = sni->getNode();
1558   pair<Node*,Node*> keyLink(outn,inn);
1559   //Don't create a new subject if it already exists
1560   if(GuiContext::getCurrent()->_mapOfSubjectControlLink.count(keyLink)!=0)
1561     return GuiContext::getCurrent()->_mapOfSubjectControlLink[keyLink];
1562
1563   SubjectControlLink *son = new SubjectControlLink(sno, sni, this);
1564   GuiContext::getCurrent()->_mapOfSubjectControlLink[keyLink] = son;
1565   _listSubjectControlLink.push_back(son);
1566   sno->addSubjectControlLink(son);
1567   sni->addSubjectControlLink(son);
1568   update(ADDCONTROLLINK, CONTROLLINK, son);
1569   DEBTRACE("addSubjectControlLink: " << getName() << " " << son->getName());
1570   return son;
1571 }
1572
1573 void SubjectComposedNode::removeControlLink(SubjectControlLink* link)
1574 {
1575   DEBTRACE("removeSubjectControlLink: " << getName());
1576
1577   Node *outn = link->getSubjectOutNode()->getNode();
1578   Node *inn = link->getSubjectInNode()->getNode();
1579   pair<Node*,Node*> keyLink(outn,inn);
1580   if (GuiContext::getCurrent()->_mapOfSubjectControlLink.count(keyLink))
1581     {
1582       DEBTRACE(outn->getName() << " " << inn->getName());
1583       GuiContext::getCurrent()->_mapOfSubjectControlLink.erase(keyLink);
1584     }
1585
1586   link->getSubjectOutNode()->removeSubjectControlLink(link);
1587   link->getSubjectInNode()->removeSubjectControlLink(link);
1588   _listSubjectControlLink.remove(link);
1589 }
1590
1591 void SubjectComposedNode::removeExternalControlLinks()
1592 {
1593   DEBTRACE("SubjectComposedNode::removeExternalControlLinks " << getName());
1594   list<SubjectControlLink*> cplcl = getSubjectControlLinks();
1595   list<SubjectControlLink*>::iterator its;
1596   ComposedNode *cnode = dynamic_cast<ComposedNode*>(getNode());
1597   for (its = cplcl.begin(); its != cplcl.end(); ++its)
1598     {
1599       bool inside = true;
1600       Node *nout = (*its)->getSubjectOutNode()->getNode();
1601       Node *nin = (*its)->getSubjectInNode()->getNode();
1602       inside = inside && cnode->isInMyDescendance(nout); // --- 0 if nout is outside
1603       inside = inside && cnode->isInMyDescendance(nin);  // --- 0 if nin is outside
1604       if (!inside)
1605         Subject::erase(*its);
1606     }
1607 }   
1608
1609 void SubjectComposedNode::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
1610 {
1611 }
1612
1613 /*!
1614  * loadLinks is used when an existing scheme has been loaded in memory, to create gui representation.
1615  * Gui representation of links is done after node representation (loadChildren).
1616  * Proc is explored recursively to find the composedNodes and create the corresponding links
1617  * representation, from bottom to top.
1618  * For each composedNode, data links representation are created first and stored in a map to avoid
1619  * double representation. Then control links representation are created.
1620  */
1621 void SubjectComposedNode::loadLinks()
1622 {
1623   list<Node *> setOfNode= _composedNode->edGetDirectDescendants();
1624   for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1625     {
1626       ComposedNode *cnSon = dynamic_cast<ComposedNode*>(*iter);
1627       if (cnSon)
1628         {
1629           SubjectNode *subSon = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(*iter)];
1630           YASSERT(subSon);
1631           SubjectComposedNode *subCnSon = dynamic_cast<SubjectComposedNode*>(subSon);
1632           YASSERT(subCnSon);
1633           subCnSon->loadLinks();
1634         }
1635     }
1636
1637   std::vector<std::pair<OutPort*,InPort*> > setOfLinks = _composedNode->getSetOfInternalLinks();
1638   std::vector<std::pair<OutPort*,InPort*> >::iterator itp;
1639   for (itp = setOfLinks.begin(); itp != setOfLinks.end(); ++itp)
1640     if (!GuiContext::getCurrent()->_mapOfSubjectLink.count(*itp))
1641       {
1642         OutPort *outp = (*itp).first;
1643         InPort *inp = (*itp).second;
1644         Node *outn = outp->getNode();
1645         Node *inn = inp->getNode();
1646         DEBTRACE(outn->getName()<<"."<<outp->getName()<<"->"<<inn->getName()<<"."<<inp->getName());
1647         SubjectNode *sno = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(outn)];
1648         SubjectNode *sni = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast<Node*>(inn)];
1649         SubjectDataPort *spo = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(outp)];
1650         SubjectDataPort *spi = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast<DataPort*>(inp)];
1651         addSubjectLink(sno,spo,sni,spi);
1652       }
1653
1654   std::list<Node*> setOfNodes = _composedNode->edGetDirectDescendants();
1655   std::list<Node*>::const_iterator itn;
1656   for(itn = setOfNodes.begin(); itn != setOfNodes.end(); ++itn)
1657     {
1658       SubjectNode* sno = GuiContext::getCurrent()->_mapOfSubjectNode[*itn];
1659       OutGate* outgate = (*itn)->getOutGate();
1660       std::list<InGate*> setIngate = outgate->edSetInGate();
1661       std::list<InGate*>::const_iterator itg;
1662       for(itg = setIngate.begin(); itg != setIngate.end(); ++itg)
1663         {
1664           Node* inNode = (*itg)->getNode();
1665           SubjectNode* sni = GuiContext::getCurrent()->_mapOfSubjectNode[inNode];
1666           if(sno && sni)
1667             addSubjectControlLink(sno,sni);
1668         }
1669     }
1670 }
1671
1672 //! Retrieves the lowest common ancestor of 2 nodes
1673 /*!
1674  * 
1675  * \note Retrieves the lowest common ancestor of 'node1' AND 'node2'. 
1676  *       If  'node1' or 'node2' are both or indiscriminately instances of ComposedNode and that
1677  *       'node1' is in descendance of 'node2' (resp. 'node2' in descendance of 'node1')
1678  *       'node2' is returned (resp. 'node1').
1679  * \exception Exception : if 'node1' and 'node2' do not share the same genealogy.
1680  * \return The lowest common ancestor if it exists.
1681  *
1682  */
1683 SubjectComposedNode* SubjectComposedNode::getLowestCommonAncestor(SubjectNode* snode1, SubjectNode* snode2)
1684 {
1685   Node* node1 = snode1->getNode();
1686   Node* node2 = snode2->getNode();
1687
1688   ComposedNode *node = ComposedNode::getLowestCommonAncestor(node1->getFather(), node2->getFather());
1689   SubjectComposedNode* snode = dynamic_cast<SubjectComposedNode*>( GuiContext::getCurrent()->_mapOfSubjectNode[node] );
1690   return snode;
1691 }
1692
1693 /*! used in derived classes using a counter, a selector, or a condition:
1694  *  ForLoop, ForEachLoop, Switch, WhileLoop.
1695  */
1696 bool SubjectComposedNode::hasValue()
1697 {
1698   return false;
1699 }
1700
1701 /*! used in derived classes using a counter, a selector, or a condition:
1702  *  ForLoop, ForEachLoop, Switch, WhileLoop.
1703  */
1704 std::string SubjectComposedNode::getValue()
1705 {
1706   return "";
1707 }
1708
1709
1710 // ----------------------------------------------------------------------------
1711
1712 SubjectBloc::SubjectBloc(YACS::ENGINE::Bloc *bloc, Subject *parent)
1713   : SubjectComposedNode(bloc, parent), _bloc(bloc)
1714 {
1715   _children.clear();
1716 }
1717
1718 /*!
1719  * all generic destruction is done in generic class SubjectNode
1720  */
1721 SubjectBloc::~SubjectBloc()
1722 {
1723   DEBTRACE("SubjectBloc::~SubjectBloc " << getName());
1724 }
1725
1726 void SubjectBloc::clean(Command *command)
1727 {
1728   if (_askRegisterUndo)
1729     {
1730       _askRegisterUndo = false;
1731       registerUndoDestroy();
1732     }
1733   localclean(command);
1734   SubjectComposedNode::clean(command);
1735 }
1736
1737 void SubjectBloc::localclean(Command *command)
1738 {
1739   DEBTRACE("SubjectBloc::localClean ");
1740   set<SubjectNode*>::iterator it;
1741   set<SubjectNode*> copyChildren = _children;
1742   for (it = copyChildren.begin(); it !=copyChildren.end(); ++it)
1743     erase(*it);
1744 }
1745
1746 SubjectNode* SubjectBloc::addNode(YACS::ENGINE::Catalog *catalog,
1747                                   std::string compo,
1748                                   std::string type,
1749                                   std::string name,
1750                                   bool newCompoInst)
1751 {
1752   DEBTRACE("SubjectBloc::addNode( " << catalog << ", " << compo << ", " << type << ", " << name << " )");
1753   SubjectNode* child = createNode(catalog, compo, type, name, newCompoInst);
1754   return child;
1755 }
1756
1757 void SubjectBloc::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
1758 {
1759   if (isCut)
1760     removeNode(son);
1761   else
1762     completeChildrenSubjectList(son);
1763 }
1764
1765 void SubjectBloc::completeChildrenSubjectList(SubjectNode *son)
1766 {
1767   _children.insert(son);
1768 }
1769
1770 void SubjectBloc::removeNode(SubjectNode* child)
1771 {
1772   _children.erase(child);
1773 }
1774
1775 SubjectNode* SubjectBloc::getChild(YACS::ENGINE::Node* node) const
1776 {
1777   SubjectNode* aChild = 0;
1778
1779   if (node)
1780   {
1781     set<SubjectNode*>::const_iterator it = _children.begin();
1782     for ( ; it != _children.end(); it++ )
1783       if ( (*it)->getNode() == node )
1784       {
1785         aChild = (*it);
1786         break;
1787       }
1788   }
1789
1790   return aChild;
1791 }
1792
1793 void SubjectBloc::recursiveUpdate(GuiEvent event, int type, Subject* son)
1794 {
1795   update(event, type, son);
1796   set<SubjectNode*>::iterator it = _children.begin();
1797   for (; it != _children.end(); ++it)
1798     (*it)->recursiveUpdate(event, type, son);
1799 }
1800
1801
1802 // ----------------------------------------------------------------------------
1803
1804 SubjectProc::SubjectProc(YACS::ENGINE::Proc *proc, Subject *parent)
1805   : SubjectBloc(proc, parent), _proc(proc)
1806 {
1807   _postEraseList.clear();
1808 }
1809
1810 SubjectProc::~SubjectProc()
1811 {
1812   DEBTRACE("SubjectProc::~SubjectProc " << getName());
1813 }
1814
1815 void SubjectProc::clean(Command *command)
1816 {
1817   if (_askRegisterUndo)
1818     {
1819       _askRegisterUndo = false;
1820       registerUndoDestroy();
1821     }
1822   localclean(command);
1823   SubjectBloc::clean(command);
1824 }
1825
1826 void SubjectProc::localclean(Command *command)
1827 {
1828   DEBTRACE("SubjectProc::localClean ");
1829 }
1830
1831 void SubjectProc::cleanPostErase()
1832 {
1833   DEBTRACE("SubjectProc::cleanPostErase");
1834   for (int i=0; i<_postEraseList.size(); i++)
1835     {
1836       DEBTRACE("cleanPostErase " << _postEraseList[i]->getName());
1837       erase(_postEraseList[i],0, true); // --- true: do not call recursively erase
1838     }
1839   _postEraseList.clear();
1840 }
1841
1842 void SubjectProc::loadProc()
1843 {
1844   DEBTRACE("SubjectProc::loadProc "  << getName());
1845   loadTypes();
1846   loadContainers();
1847   loadComponents();
1848   loadChildren();
1849   loadLinks();
1850 }
1851
1852 //! Load types for a SubjectProc
1853 /*!
1854  * This method loads (on import or on creation) all types of the builtin catalog and all types defined in the Proc
1855  */
1856 void SubjectProc::loadTypes()
1857 {
1858   Catalog* builtinCatalog = getSALOMERuntime()->getBuiltinCatalog();
1859   std::map<std::string, TypeCode *>::iterator pt;
1860   for(pt=builtinCatalog->_typeMap.begin();pt!=builtinCatalog->_typeMap.end();pt++)
1861     {
1862       addSubjectDataType((*pt).second , (*pt).first);
1863     }
1864   for(pt=_proc->typeMap.begin();pt!=_proc->typeMap.end();pt++)
1865     {
1866       addSubjectDataType((*pt).second , (*pt).first);
1867     }
1868 }
1869
1870 /*!
1871  * loadComponents is used when an existing scheme has been loaded in memory,
1872  * to create subjects for components stored in the schema file, but are not
1873  * associated with any service nodes. Note, that if such component is associated
1874  * to any container, the subject for this container is also created, if it is not
1875  * exist yet.
1876  */
1877 void SubjectProc::loadComponents()
1878 {
1879   Proc* aProc = GuiContext::getCurrent()->getProc();
1880   for (map<string, ComponentInstance*>::const_iterator itComp = aProc->componentInstanceMap.begin();
1881        itComp != aProc->componentInstanceMap.end(); ++itComp)
1882     {
1883       GuiContext::getCurrent()->_mapOfLastComponentInstance[itComp->second->getCompoName()]=itComp->second;
1884
1885       if ( GuiContext::getCurrent()->_mapOfSubjectComponent.find((*itComp).second)
1886            ==
1887            GuiContext::getCurrent()->_mapOfSubjectComponent.end() )
1888       { // engine object for component already exists => add only a subject for it
1889         addSubjectComponent((*itComp).second);
1890       }
1891     }
1892 }
1893
1894 /*!
1895  * loadContainers is used when an existing scheme has been loaded in memory,
1896  * to create subjects for containers stored in the schema file, but are not
1897  * associated with components.
1898  */
1899 void SubjectProc::loadContainers()
1900 {
1901   Proc* aProc = GuiContext::getCurrent()->getProc();
1902   for (map<string, Container*>::const_iterator itCont = aProc->containerMap.begin(); itCont != aProc->containerMap.end(); ++itCont)
1903     if ( GuiContext::getCurrent()->_mapOfSubjectContainer.find((*itCont).second) == GuiContext::getCurrent()->_mapOfSubjectContainer.end() )
1904       // engine object for container already exists => add only a subject for it
1905       addSubjectContainer((*itCont).second,(*itCont).second->getName());
1906 }
1907
1908 SubjectComponent* SubjectProc::addComponent(std::string compoName, std::string containerName)
1909 {
1910   DEBTRACE("SubjectProc::addComponent " << compoName << " " << containerName);
1911   CommandAddComponentInstance *command = new CommandAddComponentInstance(compoName, containerName);
1912   if (command->execute())
1913     {
1914       GuiContext::getCurrent()->getInvoc()->add(command);
1915       return command->getSubjectComponent();
1916     }
1917   else delete command;
1918   return 0;
1919 }
1920
1921 SubjectContainerBase *SubjectProc::addContainer(std::string name, std::string ref)
1922 {
1923   DEBTRACE("SubjectProc::addContainer " << name << " " << ref);
1924   if (! GuiContext::getCurrent()->getProc()->containerMap.count(name))
1925     {
1926       CommandAddContainer *command(new CommandAddContainer(name,ref));
1927       if (command->execute())
1928         {
1929           GuiContext::getCurrent()->getInvoc()->add(command);
1930           return command->getSubjectContainer();
1931         }
1932       else
1933           delete command;
1934     }
1935   else GuiContext::getCurrent()->_lastErrorMessage = "There is already a container with that name";
1936   return 0;
1937 }
1938
1939 SubjectContainerBase* SubjectProc::addHPContainer(std::string name, std::string ref)
1940 {
1941   DEBTRACE("SubjectProc::addContainer " << name << " " << ref);
1942   if (! GuiContext::getCurrent()->getProc()->containerMap.count(name))
1943     {
1944       CommandAddHPContainer *command(new CommandAddHPContainer(name,ref));
1945       if (command->execute())
1946         {
1947           GuiContext::getCurrent()->getInvoc()->add(command);
1948           return command->getSubjectContainer();
1949         }
1950       else
1951         delete command;
1952     }
1953   else GuiContext::getCurrent()->_lastErrorMessage = "There is already a container with that name";
1954   return 0;
1955 }
1956
1957 bool SubjectProc::addDataType(YACS::ENGINE::Catalog* catalog, std::string typeName)
1958 {
1959   DEBTRACE("SubjectProc::addDataType " << typeName);
1960   CommandAddDataTypeFromCatalog *command = new CommandAddDataTypeFromCatalog(catalog, typeName);
1961   if (command->execute())
1962     {
1963       DEBTRACE("new datatype " << typeName);
1964       GuiContext::getCurrent()->getInvoc()->add(command);
1965       return true;
1966     }
1967   else delete command;
1968   return 0;
1969 }
1970
1971 SubjectComponent* SubjectProc::addSubjectComponent(YACS::ENGINE::ComponentInstance* compo)
1972 {
1973   DEBTRACE("SubjectProc::addSubjectComponent " << compo->getInstanceName());
1974   SubjectComponent *son = new SubjectComponent(compo, this);
1975   GuiContext::getCurrent()->_mapOfSubjectComponent[compo] = son;
1976   update(ADD, COMPONENT, son);
1977   //son->setContainer();
1978   return son;
1979 }
1980
1981 SubjectContainerBase *SubjectProc::addSubjectContainer(YACS::ENGINE::Container *cont, std::string name)
1982 {
1983   DEBTRACE("SubjectProc::addSubjectContainer " << name);
1984   SubjectContainerBase *son(SubjectContainerBase::New(cont,this));
1985   // In edition mode do not clone containers
1986   // cont->attachOnCloning(); // agy : do not use _attachOnCloning attribute in edition mode. This attribute should be used now at runtime.
1987   GuiContext::getCurrent()->_mapOfSubjectContainer[cont] = son;
1988   update(ADD, CONTAINER, son);
1989   return son;
1990 }
1991
1992 /*! register a sub command when importing a node from catalog with new data types
1993  *
1994  */
1995 SubjectDataType* SubjectProc::addComSubjectDataType(YACS::ENGINE::TypeCode *type, std::string alias)
1996 {
1997   string typeName = type->name();
1998   DEBTRACE("SubjectProc::addComSubjectDataType " << typeName);
1999   SubjectDataType* son = 0;
2000   if (GuiContext::getCurrent()->isLoading())
2001     son = addSubjectDataType(type,alias); // no sub command registration
2002   else
2003     {
2004       Catalog *catalog = GuiContext::getCurrent()->getCurrentCatalog();
2005       CommandAddDataTypeFromCatalog *command = new CommandAddDataTypeFromCatalog(catalog,
2006                                                                                  typeName);
2007       if (command->execute())
2008         GuiContext::getCurrent()->getInvoc()->add(command);
2009       else delete command;
2010     }
2011   return son;
2012 }
2013
2014
2015 SubjectDataType* SubjectProc::addSubjectDataType(YACS::ENGINE::TypeCode *type, std::string alias)
2016 {
2017   string typeName = type->name();
2018   DEBTRACE("SubjectProc::addSubjectDataType " << typeName);
2019   Proc* proc = GuiContext::getCurrent()->getProc();
2020   SubjectDataType* son = 0;
2021   if (! proc->typeMap.count(typeName))
2022     proc->typeMap[ typeName ] = type->clone();
2023   else 
2024     proc->typeMap[ typeName ]->incrRef();
2025   if (! GuiContext::getCurrent()->_mapOfSubjectDataType.count(typeName))
2026     {
2027       son = new SubjectDataType(type, this, alias);
2028       GuiContext::getCurrent()->_mapOfSubjectDataType[typeName] = son;
2029       update(ADD, DATATYPE, son);
2030     }
2031   else
2032     GuiContext::getCurrent()->_lastErrorMessage = "Typecode " + typeName + " was already added in proc";
2033   return son;
2034 }
2035
2036 void SubjectProc::removeSubjectDataType(std::string typeName)
2037 {
2038   Proc* proc = GuiContext::getCurrent()->getProc();
2039   YASSERT(proc->typeMap.count(typeName));
2040   YASSERT(GuiContext::getCurrent()->_mapOfSubjectDataType.count(typeName));
2041   TypeCode* aTypeCode = proc->typeMap[typeName];
2042   SubjectDataType* aSDataType = GuiContext::getCurrent()->_mapOfSubjectDataType[typeName];
2043   unsigned int aRefCnt = aTypeCode->getRefCnt();
2044   DEBTRACE("SubjectProc::removeSubjectDataType: " << typeName << " " << aRefCnt);
2045   GuiContext::getCurrent()->_mapOfSubjectDataType.erase(typeName);
2046   proc->typeMap.erase(typeName);
2047   erase(aSDataType); // do all the necessary updates
2048   aTypeCode->decrRef();
2049 }
2050
2051 void SubjectProc::removeSubjectContainer(SubjectContainerBase* scont)
2052 {
2053   YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(scont->getContainer()));
2054   erase(scont); // do all the necessary updates
2055 }
2056
2057
2058 // ----------------------------------------------------------------------------
2059
2060 SubjectElementaryNode::SubjectElementaryNode(YACS::ENGINE::ElementaryNode *elementaryNode,
2061                                              Subject *parent)
2062   : SubjectNode(elementaryNode, parent), _elementaryNode(elementaryNode)
2063 {
2064 }
2065
2066 /*!
2067  * all generic destruction is done in generic class SubjectNode
2068  */
2069 SubjectElementaryNode::~SubjectElementaryNode()
2070 {
2071   DEBTRACE("SubjectElementaryNode::~SubjectElementaryNode " << getName());
2072 }
2073
2074 void SubjectElementaryNode::clean(Command *command)
2075 {
2076   if (_askRegisterUndo)
2077     {
2078       _askRegisterUndo = false;
2079       registerUndoDestroy();
2080     }
2081   localclean(command);
2082   SubjectNode::clean(command);
2083 }
2084
2085 void SubjectElementaryNode::localclean(Command *command)
2086 {
2087   DEBTRACE("SubjectElementaryNode::localClean ");
2088 }
2089
2090 void SubjectElementaryNode::recursiveUpdate(GuiEvent event, int type, Subject* son)
2091 {
2092   update(event, type, son);
2093 }
2094
2095 SubjectDataPort* SubjectElementaryNode::addInputPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name)
2096 {
2097   DEBTRACE("SubjectElementaryNode::addInputPort( " << catalog << ", " << type << ", " << name << " )");
2098   Proc *proc = GuiContext::getCurrent()->getProc();
2099   string position = "";
2100   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
2101   else YASSERT(0);
2102   CommandAddInputPortFromCatalog *command = new CommandAddInputPortFromCatalog(catalog,
2103                                                                                type,
2104                                                                                position,
2105                                                                                name);
2106   if (command->execute())
2107     {
2108       GuiContext::getCurrent()->getInvoc()->add(command);
2109       SubjectInputPort *son = command->getSubjectInputPort();
2110       return son;
2111     }
2112   else delete command;
2113   return 0;
2114 }
2115
2116 SubjectDataPort* SubjectElementaryNode::addOutputPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name)
2117 {
2118   DEBTRACE("SubjectElementaryNode::addOutputPort( " << catalog << ", " << type << ", " << name << " )");
2119   Proc *proc = GuiContext::getCurrent()->getProc();
2120   string position = "";
2121   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
2122   else YASSERT(0);
2123   CommandAddOutputPortFromCatalog *command = new CommandAddOutputPortFromCatalog(catalog,
2124                                                                                  type,
2125                                                                                  position,
2126                                                                                  name);
2127   if (command->execute())
2128     {
2129       GuiContext::getCurrent()->getInvoc()->add(command);
2130       SubjectOutputPort *son = command->getSubjectOutputPort();
2131       return son;
2132     }
2133   else delete command;
2134   return 0;
2135 }
2136
2137 SubjectDataPort* SubjectElementaryNode::addIDSPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name)
2138 {
2139   DEBTRACE("SubjectElementaryNode::addIDSPort( " << catalog << ", " << type << ", " << name << " )");
2140   Proc *proc = GuiContext::getCurrent()->getProc();
2141   string position = "";
2142   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
2143   else YASSERT(0);
2144   CommandAddIDSPortFromCatalog *command = new CommandAddIDSPortFromCatalog(catalog,
2145                                                                            type,
2146                                                                            position,
2147                                                                            name);
2148   if (command->execute())
2149     {
2150       GuiContext::getCurrent()->getInvoc()->add(command);
2151       SubjectInputDataStreamPort *son = command->getSubjectIDSPort();
2152       return son;
2153     }
2154   else delete command;
2155   return 0;
2156 }
2157
2158 SubjectDataPort* SubjectElementaryNode::addODSPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name)
2159 {
2160   DEBTRACE("SubjectElementaryNode::addODSPort( " << catalog << ", " << type << ", " << name << " )");
2161   Proc *proc = GuiContext::getCurrent()->getProc();
2162   string position = "";
2163   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
2164   else YASSERT(0);
2165   CommandAddODSPortFromCatalog *command = new CommandAddODSPortFromCatalog(catalog,
2166                                                                            type,
2167                                                                            position,
2168                                                                            name);
2169   if (command->execute())
2170     {
2171       GuiContext::getCurrent()->getInvoc()->add(command);
2172       SubjectOutputDataStreamPort *son = command->getSubjectODSPort();
2173       return son;
2174     }
2175   else delete command;
2176   return 0;
2177 }
2178
2179 bool SubjectElementaryNode::OrderDataPorts(SubjectDataPort* portToMove, int isUp)
2180 {
2181   DEBTRACE("SubjectElementaryNode::OrderDataPorts");
2182   Proc *proc = GuiContext::getCurrent()->getProc();
2183   string position = "";
2184   if (proc != dynamic_cast<Proc*>(_node)) position = proc->getChildName(_node);
2185   else YASSERT(0);
2186
2187   if (!portToMove) return false;
2188   string nameToMove = portToMove->getName();
2189
2190   Command *command = 0;
2191   bool isInput = dynamic_cast<SubjectInputPort*>(portToMove);
2192   if (isInput)
2193     command = new CommandOrderInputPorts(position, nameToMove, isUp);
2194   else
2195     command = new CommandOrderOutputPorts(position, nameToMove, isUp);
2196
2197   if (command->execute())
2198     {
2199       GuiContext::getCurrent()->getInvoc()->add(command);
2200       return true;
2201     }
2202   return false;
2203 }
2204       
2205 void SubjectElementaryNode::removePort(SubjectDataPort* port)
2206 {
2207   DEBTRACE("SubjectElementaryNode::removePort " << port->getName());
2208   if (SubjectInputPort* inp = dynamic_cast<SubjectInputPort*>(port))
2209     {
2210       DEBTRACE("-");
2211       _listSubjectInputPort.remove(inp);
2212     }
2213   else if(SubjectOutputPort* outp = dynamic_cast<SubjectOutputPort*>(port))
2214     {
2215       DEBTRACE("--");
2216       _listSubjectOutputPort.remove(outp);
2217     }
2218   if (SubjectInputDataStreamPort* idsp = dynamic_cast<SubjectInputDataStreamPort*>(port))
2219     {
2220       DEBTRACE("---");
2221       _listSubjectIDSPort.remove(idsp);
2222     }
2223   else if(SubjectOutputDataStreamPort* odsp = dynamic_cast<SubjectOutputDataStreamPort*>(port))
2224     {
2225       DEBTRACE("----");
2226       _listSubjectODSPort.remove(odsp);
2227     }
2228 }
2229
2230 void SubjectElementaryNode::loadChildren()
2231 {
2232   list<InputPort*>  listInputPorts  = _elementaryNode->getLocalInputPorts();
2233   list<OutputPort*> listOutputPorts = _elementaryNode->getLocalOutputPorts();
2234   list<InputDataStreamPort*>  listIDSPorts = _elementaryNode->getSetOfInputDataStreamPort();
2235   list<OutputDataStreamPort*> listODSPorts = _elementaryNode->getSetOfOutputDataStreamPort();
2236   if (SplitterNode *splitterNode = dynamic_cast<SplitterNode*>(_elementaryNode))
2237     listInputPorts.push_back(splitterNode->getFather()->getInputPort("SmplsCollection"));
2238   list<InputPort*>::const_iterator iti;
2239   for (iti = listInputPorts.begin(); iti != listInputPorts.end(); ++iti)
2240     addSubjectInputPort(*iti);
2241   list<OutputPort*>::const_iterator ito;
2242   for (ito = listOutputPorts.begin(); ito != listOutputPorts.end(); ++ito)
2243     addSubjectOutputPort(*ito);
2244   list<InputDataStreamPort*>::const_iterator itids;
2245   for (itids = listIDSPorts.begin(); itids != listIDSPorts.end(); ++itids)
2246     addSubjectIDSPort(*itids);
2247   list<OutputDataStreamPort*>::const_iterator itods;
2248   for (itods = listODSPorts.begin(); itods != listODSPorts.end(); ++itods)
2249     addSubjectODSPort(*itods);
2250 }
2251
2252 void SubjectElementaryNode::saveLinks()
2253 {
2254   SubjectNode::saveLinks();
2255 }
2256
2257 void SubjectElementaryNode::restoreLinks()
2258 {
2259   SubjectNode::restoreLinks();
2260 }
2261
2262
2263 // ----------------------------------------------------------------------------
2264
2265
2266 SubjectInlineNode::SubjectInlineNode(YACS::ENGINE::InlineNode *inlineNode, Subject *parent)
2267   : SubjectElementaryNode(inlineNode, parent), _inlineNode(inlineNode)
2268 {
2269 }
2270
2271 SubjectInlineNode::~SubjectInlineNode()
2272 {
2273   DEBTRACE("SubjectInlineNode::~SubjectInlineNode " << getName());
2274 }
2275
2276 bool SubjectInlineNode::setScript(std::string script)
2277 {
2278   Proc *proc = GuiContext::getCurrent()->getProc();
2279   CommandSetInlineNodeScript *command =
2280     new CommandSetInlineNodeScript(proc->getChildName(_node), script);
2281   if (command->execute())
2282     {
2283       GuiContext::getCurrent()->getInvoc()->add(command);
2284       return true;
2285     }
2286   else delete command;
2287   return false;
2288 }
2289
2290 std::string SubjectInlineNode::getScript()
2291 {
2292   return _inlineNode->getScript();
2293 }
2294
2295 void SubjectInlineNode::clean(Command *command)
2296 {
2297   if (_askRegisterUndo)
2298     {
2299       _askRegisterUndo = false;
2300       registerUndoDestroy();
2301     }
2302   localclean(command);
2303   SubjectElementaryNode::clean(command);
2304 }
2305
2306 void SubjectInlineNode::localclean(Command *command)
2307 {
2308   DEBTRACE("SubjectInlineNode::localClean ");
2309 }
2310
2311 bool SubjectInlineNode::setExecutionMode(const std::string& mode)
2312 {
2313   DEBTRACE("SubjectInlineNode::setExecutionMode ");
2314   Proc *proc = GuiContext::getCurrent()->getProc();
2315
2316   CommandSetExecutionMode *command = new CommandSetExecutionMode(proc->getChildName(_node), mode);
2317   if (command->execute())
2318     {
2319       if (!GuiContext::getCurrent()->isLoading()) // do not register command when loading a schema
2320         GuiContext::getCurrent()->getInvoc()->add(command);
2321       else delete command;
2322       return true;
2323     }
2324   else delete command;
2325   return false;
2326 }
2327
2328 bool SubjectInlineNode::setContainer(SubjectContainerBase *scont)
2329 {
2330   DEBTRACE("SubjectInlineNode::setContainer ");
2331   Proc *proc = GuiContext::getCurrent()->getProc();
2332
2333   CommandSetContainer *command = new CommandSetContainer(proc->getChildName(_node), scont->getName());
2334   if (command->execute())
2335     {
2336       if (!GuiContext::getCurrent()->isLoading()) // do not register command when loading a schema
2337         GuiContext::getCurrent()->getInvoc()->add(command);
2338       else delete command;
2339       return true;
2340     }
2341   else delete command;
2342   return false;
2343 }
2344
2345
2346 // ----------------------------------------------------------------------------
2347
2348 SubjectServiceNode::SubjectServiceNode(YACS::ENGINE::ServiceNode *serviceNode, Subject *parent)
2349   : SubjectElementaryNode(serviceNode, parent), _serviceNode(serviceNode)
2350 {
2351   _subjectReference = 0;
2352   _subRefComponent = 0;
2353 }
2354
2355 SubjectServiceNode::~SubjectServiceNode()
2356 {
2357   DEBTRACE("SubjectServiceNode::~SubjectServiceNode " << getName());
2358   ComponentInstance *instance = _serviceNode->getComponent();
2359   if (!instance) return;
2360   if (GuiContext::getCurrent()->_mapOfSubjectComponent.count(instance))
2361     {
2362       SubjectComponent *scomp = GuiContext::getCurrent()->_mapOfSubjectComponent[instance];
2363       if (!scomp->hasServices())
2364         GuiContext::getCurrent()->getSubjectProc()->addPostErase(scomp);
2365     }
2366 }
2367
2368 void SubjectServiceNode::clean(Command *command)
2369 {
2370   if (_askRegisterUndo)
2371     {
2372       _askRegisterUndo = false;
2373       registerUndoDestroy();
2374     }
2375   localclean(command);
2376   SubjectElementaryNode::clean(command);
2377 }
2378
2379 void SubjectServiceNode::localclean(Command *command)
2380 {
2381   DEBTRACE("SubjectServiceNode::localClean ");
2382   if (_subRefComponent)
2383     {
2384       SubjectComponent *scomp = dynamic_cast<SubjectComponent*>(_subRefComponent->getParent());
2385       if (scomp)
2386         scomp->removeSubServiceFromSet(this);
2387     }
2388   if (_subjectReference)
2389     {
2390 //       update( REMOVE, REFERENCE, _subjectReference );
2391       erase(_subjectReference);
2392       _subjectReference = 0;
2393     }
2394   if (_subRefComponent)
2395     {
2396       erase(_subRefComponent);
2397       _subRefComponent = 0;
2398     }
2399 }
2400
2401
2402 /*!
2403  *  When cloning a service node from a catalog, create the component associated to the node,
2404  *  if not already existing, and create the corresponding subject.
2405  */
2406 void SubjectServiceNode::setComponentFromCatalog(YACS::ENGINE::Catalog *catalog,
2407                                                  std::string compo,
2408                                                  std::string service)
2409 {
2410   DEBTRACE("SubjectServiceNode::setComponentFromCatalog " << compo);
2411
2412   Proc* proc = GuiContext::getCurrent()->getProc();
2413   string position = proc->getChildName(_node);
2414   CommandAddComponentFromCatalog* command =
2415     new CommandAddComponentFromCatalog(catalog,
2416                                        position,
2417                                        compo,
2418                                        service);
2419   if (command->execute())
2420     GuiContext::getCurrent()->getInvoc()->add(command);
2421   else delete command;
2422   return;
2423 }
2424
2425 /*!
2426  *  When loading scheme from file, get the component associated to the node, if any,
2427  *  and create the corresponding subject.
2428  */
2429 void SubjectServiceNode::setComponent()
2430 {
2431   DEBTRACE("SubjectServiceNode::setComponent");
2432   ComponentInstance *instance = _serviceNode->getComponent();
2433   if (instance)
2434     {
2435       Proc* proc = GuiContext::getCurrent()->getProc();
2436       string compo = instance->getCompoName();
2437       SubjectComponent* subCompo = 0;
2438       if (! GuiContext::getCurrent()->_mapOfSubjectComponent.count(instance))
2439         {
2440           DEBTRACE("SubjectServiceNode::setComponent : create subject for compo = " << compo.c_str());
2441           if(proc->componentInstanceMap.count(instance->getInstanceName())==0)
2442             {
2443               std::cerr << "PROBLEM : ComponentInstance should be registered in proc, add it " << instance->getInstanceName() << std::endl;
2444               proc->componentInstanceMap[instance->getInstanceName()] = instance;
2445               Container* cont=instance->getContainer();
2446               //check if the associated container is consistent with containerMap
2447               if(cont)
2448                 if (proc->containerMap.count(cont->getName()) == 0)
2449                   {
2450                     //container exists but is not in containerMap. Clone it, it's probably the result of copy paste from outside the proc
2451                     Container* newcont(cont->cloneAlways());
2452                     proc->containerMap[cont->getName()]=newcont;
2453                     instance->setContainer(newcont);
2454                     GuiContext::getCurrent()->getSubjectProc()->addSubjectContainer(newcont, newcont->getName());
2455                   }
2456                 else
2457                   {
2458                     if(cont != proc->containerMap[cont->getName()])
2459                       {
2460                         //the associated container is not the same as the one in containerMap: use the containerMap one
2461                         instance->setContainer(proc->containerMap[cont->getName()]);
2462                       }
2463                   }
2464             }
2465           subCompo = GuiContext::getCurrent()->getSubjectProc()->addSubjectComponent(instance);
2466         }
2467       else
2468         {
2469           DEBTRACE("SubjectServiceNode::setComponent : get already created subject for compo = " <<compo.c_str());
2470           subCompo = GuiContext::getCurrent()->_mapOfSubjectComponent[instance];
2471         }       
2472       YASSERT(subCompo);
2473       addSubjectReference(subCompo);
2474       if (_subRefComponent)
2475         subCompo->moveService(_subRefComponent);
2476       else
2477         _subRefComponent = subCompo->attachService(this);
2478     }
2479 }
2480
2481 bool SubjectServiceNode::associateToComponent(SubjectComponent *subcomp)
2482 {
2483   DEBTRACE("SubjectServiceNode::associateToComponent " << getName() << " " << subcomp->getName());
2484   SubjectReference* oldSReference = _subjectReference;
2485   string aName = GuiContext::getCurrent()->getProc()->getChildName(_serviceNode);
2486   CommandAssociateServiceToComponent *command =
2487     new CommandAssociateServiceToComponent(aName, subcomp->getName());
2488   if (command->execute())
2489     {
2490       GuiContext::getCurrent()->getInvoc()->add(command);
2491       return true;
2492     }
2493   else delete command;
2494   return false;
2495 }
2496
2497 void SubjectServiceNode::addSubjectReference(Subject *ref)
2498 {
2499   DEBTRACE("Subject::addSubjectReference " << getName() << " " << ref->getName());
2500   SubjectReference *son = new SubjectReference(ref, this);
2501   _subjectReference = son;
2502   update(ADDREF, 0, son);
2503 }
2504
2505 SubjectReference* SubjectServiceNode::getSubjectReference()
2506 {
2507   return _subjectReference;
2508 }
2509
2510 // ----------------------------------------------------------------------------
2511
2512 SubjectPythonNode::SubjectPythonNode(YACS::ENGINE::PythonNode *pythonNode, Subject *parent)
2513   : SubjectInlineNode(pythonNode, parent), _pythonNode(pythonNode)
2514 {
2515 }
2516
2517 SubjectPythonNode::~SubjectPythonNode()
2518 {
2519   DEBTRACE("SubjectPythonNode::~SubjectPythonNode " << getName());
2520 }
2521
2522 void SubjectPythonNode::clean(Command *command)
2523 {
2524   if (_askRegisterUndo)
2525     {
2526       _askRegisterUndo = false;
2527       registerUndoDestroy();
2528     }
2529   localclean(command);
2530   SubjectInlineNode::clean(command);
2531 }
2532
2533 void SubjectPythonNode::localclean(Command *command)
2534 {
2535   DEBTRACE("SubjectPythonNode::localClean ");
2536 }
2537
2538
2539 // ----------------------------------------------------------------------------
2540
2541 SubjectPyFuncNode::SubjectPyFuncNode(YACS::ENGINE::PyFuncNode *pyFuncNode, Subject *parent)
2542   : SubjectInlineNode(pyFuncNode, parent), _pyFuncNode(pyFuncNode)
2543 {
2544 }
2545
2546 SubjectPyFuncNode::~SubjectPyFuncNode()
2547 {
2548   DEBTRACE("SubjectPyFuncNode::~SubjectPyFuncNode " << getName());
2549 }
2550
2551 bool SubjectPyFuncNode::setFunctionName(std::string funcName)
2552 {
2553   Proc *proc = GuiContext::getCurrent()->getProc();
2554   CommandSetFuncNodeFunctionName *command =
2555     new CommandSetFuncNodeFunctionName(proc->getChildName(_node), funcName);
2556   if (command->execute())
2557     {
2558       GuiContext::getCurrent()->getInvoc()->add(command);
2559       return true;
2560     }
2561   else delete command;
2562   return false;
2563 }
2564
2565 void SubjectPyFuncNode::clean(Command *command)
2566 {
2567   if (_askRegisterUndo)
2568     {
2569       _askRegisterUndo = false;
2570       registerUndoDestroy();
2571     }
2572   localclean(command);
2573   SubjectInlineNode::clean(command);
2574 }
2575
2576 void SubjectPyFuncNode::localclean(Command *command)
2577 {
2578   DEBTRACE("SubjectPyFuncNode::localClean ");
2579 }
2580
2581 // ----------------------------------------------------------------------------
2582
2583 SubjectCORBANode::SubjectCORBANode(YACS::ENGINE::CORBANode *corbaNode, Subject *parent)
2584   : SubjectServiceNode(corbaNode, parent), _corbaNode(corbaNode)
2585 {
2586 }
2587
2588 SubjectCORBANode::~SubjectCORBANode()
2589 {
2590   DEBTRACE("SubjectCORBANode::~SubjectCORBANode " << getName());
2591 }
2592
2593 void SubjectCORBANode::clean(Command *command)
2594 {
2595   if (_askRegisterUndo)
2596     {
2597       _askRegisterUndo = false;
2598       registerUndoDestroy();
2599     }
2600   localclean(command);
2601   SubjectServiceNode::clean(command);
2602 }
2603
2604 void SubjectCORBANode::localclean(Command *command)
2605 {
2606   DEBTRACE("SubjectCORBANode::localClean ");
2607 }
2608
2609
2610 // ----------------------------------------------------------------------------
2611
2612 SubjectCppNode::SubjectCppNode(YACS::ENGINE::CppNode *cppNode, Subject *parent)
2613   : SubjectServiceNode(cppNode, parent), _cppNode(cppNode)
2614 {
2615 }
2616
2617 SubjectCppNode::~SubjectCppNode()
2618 {
2619   DEBTRACE("SubjectCppNode::~SubjectCppNode " << getName());
2620 }
2621
2622 void SubjectCppNode::clean(Command *command)
2623 {
2624   if (_askRegisterUndo)
2625     {
2626       _askRegisterUndo = false;
2627       registerUndoDestroy();
2628     }
2629   localclean(command);
2630   SubjectServiceNode::clean(command);
2631 }
2632
2633 void SubjectCppNode::localclean(Command *command)
2634 {
2635   DEBTRACE("SubjectCppNode::localClean ");
2636 }
2637
2638
2639 // ----------------------------------------------------------------------------
2640
2641 SubjectSalomeNode::SubjectSalomeNode(YACS::ENGINE::SalomeNode *salomeNode, Subject *parent)
2642   : SubjectServiceNode(salomeNode, parent), _salomeNode(salomeNode)
2643 {
2644 }
2645
2646 SubjectSalomeNode::~SubjectSalomeNode()
2647 {
2648   DEBTRACE("SubjectSalomeNode::~SubjectSalomeNode " << getName());
2649 }
2650
2651 void SubjectSalomeNode::clean(Command *command)
2652 {
2653   if (_askRegisterUndo)
2654     {
2655       _askRegisterUndo = false;
2656       registerUndoDestroy();
2657     }
2658   localclean(command);
2659   SubjectServiceNode::clean(command);
2660 }
2661
2662 void SubjectSalomeNode::localclean(Command *command)
2663 {
2664   DEBTRACE("SubjectSalomeNode::localClean ");
2665 }
2666
2667
2668 // ----------------------------------------------------------------------------
2669
2670 SubjectSalomePythonNode::SubjectSalomePythonNode(YACS::ENGINE::SalomePythonNode *salomePythonNode,
2671                                                  Subject *parent)
2672   : SubjectServiceNode(salomePythonNode, parent), _salomePythonNode(salomePythonNode)
2673 {
2674 }
2675
2676 SubjectSalomePythonNode::~SubjectSalomePythonNode()
2677 {
2678   DEBTRACE("SubjectSalomePythonNode::~SubjectSalomePythonNode " << getName());
2679 }
2680
2681 void SubjectSalomePythonNode::clean(Command *command)
2682 {
2683   if (_askRegisterUndo)
2684     {
2685       _askRegisterUndo = false;
2686       registerUndoDestroy();
2687     }
2688   localclean(command);
2689   SubjectServiceNode::clean(command);
2690 }
2691
2692 void SubjectSalomePythonNode::localclean(Command *command)
2693 {
2694   DEBTRACE("SubjectSalomePythonNode::localClean ");
2695 }
2696
2697
2698 // ----------------------------------------------------------------------------
2699
2700 SubjectXmlNode::SubjectXmlNode(YACS::ENGINE::XmlNode *xmlNode, Subject *parent)
2701   : SubjectServiceNode(xmlNode, parent), _xmlNode(xmlNode)
2702 {
2703 }
2704
2705 SubjectXmlNode::~SubjectXmlNode()
2706 {
2707   DEBTRACE("SubjectXmlNode::~SubjectXmlNode " << getName());
2708 }
2709
2710 void SubjectXmlNode::clean(Command *command)
2711 {
2712   if (_askRegisterUndo)
2713     {
2714       _askRegisterUndo = false;
2715       registerUndoDestroy();
2716     }
2717   localclean(command);
2718   SubjectServiceNode::clean(command);
2719 }
2720
2721 void SubjectXmlNode::localclean(Command *command)
2722 {
2723   DEBTRACE("SubjectXmlNode::localClean ");
2724 }
2725
2726
2727 // ----------------------------------------------------------------------------
2728
2729 SubjectSplitterNode::SubjectSplitterNode(YACS::ENGINE::SplitterNode *splitterNode, Subject *parent)
2730   : SubjectElementaryNode(splitterNode, parent), _splitterNode(splitterNode)
2731 {
2732   _destructible = false;
2733 }
2734
2735 SubjectSplitterNode::~SubjectSplitterNode()
2736 {
2737   DEBTRACE("SubjectSplitterNode::~SubjectSplitterNode " << getName());
2738 }
2739
2740 void SubjectSplitterNode::clean(Command *command)
2741 {
2742   if (_askRegisterUndo)
2743     {
2744       _askRegisterUndo = false;
2745       registerUndoDestroy();
2746     }
2747   localclean(command);
2748   SubjectElementaryNode::clean(command);
2749 }
2750
2751 void SubjectSplitterNode::localclean(Command *command)
2752 {
2753   DEBTRACE("SubjectSplitterNode::localClean ");
2754 }
2755
2756
2757 std::string SubjectSplitterNode::getName()
2758 {
2759   return "splitter";
2760 }
2761
2762 // ----------------------------------------------------------------------------
2763
2764 SubjectDataNode::SubjectDataNode(YACS::ENGINE::DataNode *dataNode, Subject *parent)
2765   : SubjectElementaryNode(dataNode, parent), _dataNode(dataNode)
2766 {
2767   _destructible = true;
2768 }
2769
2770 SubjectDataNode::~SubjectDataNode()
2771 {
2772   DEBTRACE("SubjectDataNode::~SubjectDataNode " << getName());
2773 }
2774
2775 void SubjectDataNode::clean(Command *command)
2776 {
2777   if (_askRegisterUndo)
2778     {
2779       _askRegisterUndo = false;
2780       registerUndoDestroy();
2781     }
2782   localclean(command);
2783   SubjectElementaryNode::clean(command);
2784 }
2785
2786 void SubjectDataNode::localclean(Command *command)
2787 {
2788   DEBTRACE("SubjectDataNode::localClean ");
2789 }
2790
2791 // ----------------------------------------------------------------------------
2792
2793 SubjectPresetNode::SubjectPresetNode(YACS::ENGINE::PresetNode *presetNode, Subject *parent)
2794   : SubjectDataNode(presetNode, parent), _presetNode(presetNode)
2795 {
2796   _destructible = true;
2797 }
2798
2799 SubjectPresetNode::~SubjectPresetNode()
2800 {
2801   DEBTRACE("SubjectPresetNode::~SubjectPresetNode " << getName());
2802 }
2803
2804 void SubjectPresetNode::clean(Command *command)
2805 {
2806   if (_askRegisterUndo)
2807     {
2808       _askRegisterUndo = false;
2809       registerUndoDestroy();
2810     }
2811   localclean(command);
2812   SubjectDataNode::clean(command);
2813 }
2814
2815 void SubjectPresetNode::localclean(Command *command)
2816 {
2817   DEBTRACE("SubjectPresetNode::localClean ");
2818 }
2819
2820 // ----------------------------------------------------------------------------
2821
2822 SubjectOutNode::SubjectOutNode(YACS::ENGINE::OutNode *outNode, Subject *parent)
2823   : SubjectDataNode(outNode, parent), _outNode(outNode)
2824 {
2825   _destructible = true;
2826 }
2827
2828 SubjectOutNode::~SubjectOutNode()
2829 {
2830   DEBTRACE("SubjectOutNode::~SubjectOutNode " << getName());
2831 }
2832
2833 void SubjectOutNode::clean(Command *command)
2834 {
2835   if (_askRegisterUndo)
2836     {
2837       _askRegisterUndo = false;
2838       registerUndoDestroy();
2839     }
2840   localclean(command);
2841   SubjectDataNode::clean(command);
2842 }
2843
2844 void SubjectOutNode::localclean(Command *command)
2845 {
2846   DEBTRACE("SubjectOutNode::localClean ");
2847 }
2848
2849 // ----------------------------------------------------------------------------
2850
2851 SubjectStudyInNode::SubjectStudyInNode(YACS::ENGINE::StudyInNode *studyInNode, Subject *parent)
2852   : SubjectDataNode(studyInNode, parent), _studyInNode(studyInNode)
2853 {
2854   _destructible = true;
2855 }
2856
2857 SubjectStudyInNode::~SubjectStudyInNode()
2858 {
2859   DEBTRACE("SubjectStudyInNode::~SubjectStudyInNode " << getName());
2860 }
2861
2862 void SubjectStudyInNode::clean(Command *command)
2863 {
2864   if (_askRegisterUndo)
2865     {
2866       _askRegisterUndo = false;
2867       registerUndoDestroy();
2868     }
2869   localclean(command);
2870   SubjectDataNode::clean(command);
2871 }
2872
2873 void SubjectStudyInNode::localclean(Command *command)
2874 {
2875   DEBTRACE("SubjectStudyInNode::localClean ");
2876 }
2877
2878 // ----------------------------------------------------------------------------
2879
2880 SubjectStudyOutNode::SubjectStudyOutNode(YACS::ENGINE::StudyOutNode *studyOutNode, Subject *parent)
2881   : SubjectDataNode(studyOutNode, parent), _studyOutNode(studyOutNode)
2882 {
2883   _destructible = true;
2884 }
2885
2886 SubjectStudyOutNode::~SubjectStudyOutNode()
2887 {
2888   DEBTRACE("SubjectStudyOutNode::~SubjectStudyOutNode " << getName());
2889 }
2890
2891 void SubjectStudyOutNode::clean(Command *command)
2892 {
2893   if (_askRegisterUndo)
2894     {
2895       _askRegisterUndo = false;
2896       registerUndoDestroy();
2897     }
2898   localclean(command);
2899   SubjectDataNode::clean(command);
2900 }
2901
2902 void SubjectStudyOutNode::localclean(Command *command)
2903 {
2904   DEBTRACE("SubjectStudyOutNode::localClean ");
2905 }
2906
2907 // ----------------------------------------------------------------------------
2908
2909 SubjectForLoop::SubjectForLoop(YACS::ENGINE::ForLoop *forLoop, Subject *parent)
2910   : SubjectComposedNode(forLoop, parent), _forLoop(forLoop)
2911 {
2912   _body = 0;
2913 }
2914
2915 SubjectForLoop::~SubjectForLoop()
2916 {
2917   DEBTRACE("SubjectForLoop::~SubjectForLoop " << getName());
2918 }
2919
2920 void SubjectForLoop::clean(Command *command)
2921 {
2922   if (_askRegisterUndo)
2923     {
2924       _askRegisterUndo = false;
2925       registerUndoDestroy();
2926     }
2927   localclean(command);
2928   SubjectComposedNode::clean(command);
2929 }
2930
2931 void SubjectForLoop::localclean(Command *command)
2932 {
2933   DEBTRACE("SubjectForLoop::localClean ");
2934   if (_body)
2935     erase(_body);
2936 }
2937
2938 void SubjectForLoop::recursiveUpdate(GuiEvent event, int type, Subject* son)
2939 {
2940   update(event, type, son);
2941   if (_body)
2942     _body->recursiveUpdate(event, type, son);
2943 }
2944
2945 SubjectNode* SubjectForLoop::addNode(YACS::ENGINE::Catalog *catalog,
2946                                      std::string compo,
2947                                      std::string type,
2948                                      std::string name,
2949                                      bool newCompoInst)
2950 {
2951   DEBTRACE("SubjectForLoop::addNode("<<catalog<<","<<compo<<","<<type<<","<<name<<")");
2952   SubjectNode* body = 0;
2953   if (_body)
2954     {
2955       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a loop, put the nodes in a bloc"; 
2956       return body;
2957     }
2958   body = createNode(catalog, compo, type, name, newCompoInst);
2959   return body;
2960 }
2961
2962 void SubjectForLoop::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
2963 {
2964   if (isCut)
2965     _body = 0;
2966   else
2967     _body = son;
2968 }
2969
2970 void SubjectForLoop::completeChildrenSubjectList(SubjectNode *son)
2971 {
2972   _body = son;
2973 }
2974
2975 bool SubjectForLoop::setNbSteps(std::string nbSteps)
2976 {
2977   DEBTRACE("SubjectForLoop::setNbSteps " << nbSteps);
2978   Proc *proc = GuiContext::getCurrent()->getProc();
2979   CommandSetForLoopSteps *command =
2980     new CommandSetForLoopSteps(proc->getChildName(getNode()), nbSteps);
2981   if (command->execute())
2982     {
2983       GuiContext::getCurrent()->getInvoc()->add(command);
2984       return true;
2985     }
2986   else delete command;
2987   return false;
2988 }
2989 bool SubjectForLoop::hasValue()
2990 {
2991   return true;
2992 }
2993
2994 std::string SubjectForLoop::getValue()
2995 {
2996   return _forLoop->edGetNbOfTimesInputPort()->getAsString();
2997 }
2998
2999 // ----------------------------------------------------------------------------
3000
3001 SubjectWhileLoop::SubjectWhileLoop(YACS::ENGINE::WhileLoop *whileLoop, Subject *parent)
3002   : SubjectComposedNode(whileLoop, parent), _whileLoop(whileLoop)
3003 {
3004   _body = 0;
3005 }
3006
3007 SubjectWhileLoop::~SubjectWhileLoop()
3008 {
3009   DEBTRACE("SubjectWhileLoop::~SubjectWhileLoop " << getName());
3010 }
3011
3012 void SubjectWhileLoop::clean(Command *command)
3013 {
3014   if (_askRegisterUndo)
3015     {
3016       _askRegisterUndo = false;
3017       registerUndoDestroy();
3018     }
3019   localclean(command);
3020   SubjectComposedNode::clean(command);
3021 }
3022
3023 void SubjectWhileLoop::localclean(Command *command)
3024 {
3025   DEBTRACE("SubjectWhileLoop::localClean ");
3026   if (_body)
3027     erase(_body);
3028 }
3029
3030 void SubjectWhileLoop::recursiveUpdate(GuiEvent event, int type, Subject* son)
3031 {
3032   update(event, type, son);
3033   if (_body)
3034     _body->recursiveUpdate(event, type, son);
3035 }
3036
3037 SubjectNode* SubjectWhileLoop::addNode(YACS::ENGINE::Catalog *catalog,
3038                                        std::string compo,
3039                                        std::string type,
3040                                        std::string name,
3041                                        bool newCompoInst)
3042 {
3043   DEBTRACE("SubjectWhileLoop::addNode(catalog, compo, type, name)");
3044   SubjectNode* body = 0;
3045   if (_body)
3046     {
3047       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a loop, put the nodes in a bloc"; 
3048       return body;
3049     }
3050   body = createNode(catalog, compo, type, name, newCompoInst);
3051   return body;
3052 }
3053
3054 void SubjectWhileLoop::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
3055 {
3056   if (isCut)
3057     _body = 0;
3058   else
3059     _body = son;
3060 }
3061
3062 void SubjectWhileLoop::completeChildrenSubjectList(SubjectNode *son)
3063 {
3064   _body = son;
3065 }
3066
3067 bool SubjectWhileLoop::setCondition(std::string condition)
3068 {
3069   DEBTRACE("SubjectWhileLoop::setCondition " << condition);
3070   Proc *proc = GuiContext::getCurrent()->getProc();
3071   CommandSetWhileCondition *command =
3072     new CommandSetWhileCondition(proc->getChildName(getNode()), condition);
3073   if (command->execute())
3074     {
3075       GuiContext::getCurrent()->getInvoc()->add(command);
3076       return true;
3077     }
3078   else delete command;
3079   return false;
3080 }
3081
3082 bool SubjectWhileLoop::hasValue()
3083 {
3084   return true;
3085 }
3086
3087 std::string SubjectWhileLoop::getValue()
3088 {
3089   return _whileLoop->edGetConditionPort()->getAsString();
3090 }
3091
3092 // ----------------------------------------------------------------------------
3093
3094 SubjectSwitch::SubjectSwitch(YACS::ENGINE::Switch *aSwitch, Subject *parent)
3095   : SubjectComposedNode(aSwitch, parent), _switch(aSwitch)
3096 {
3097   _bodyMap.clear();
3098 }
3099
3100 SubjectSwitch::~SubjectSwitch()
3101 {
3102   DEBTRACE("SubjectSwitch::~SubjectSwitch " << getName());
3103 }
3104
3105 void SubjectSwitch::clean(Command *command)
3106 {
3107   if (_askRegisterUndo)
3108     {
3109       _askRegisterUndo = false;
3110       registerUndoDestroy();
3111     }
3112   localclean(command);
3113   SubjectComposedNode::clean(command);
3114 }
3115
3116 void SubjectSwitch::localclean(Command *command)
3117 {
3118   DEBTRACE("SubjectSwitch::localClean ");
3119   map<int, SubjectNode*>::iterator it;
3120   map<int, SubjectNode*> bodyMapCpy = _bodyMap;
3121   for (it = bodyMapCpy.begin(); it != bodyMapCpy.end(); ++it)
3122     erase((*it).second);
3123 }
3124
3125 void SubjectSwitch::recursiveUpdate(GuiEvent event, int type, Subject* son)
3126 {
3127   update(event, type, son);
3128   map<int, SubjectNode*>::iterator it = _bodyMap.begin();
3129   for (; it != _bodyMap.end(); ++it)
3130     (*it).second->recursiveUpdate(event, type, son);
3131 }
3132
3133 SubjectNode* SubjectSwitch::addNode(YACS::ENGINE::Catalog *catalog,
3134                                     std::string compo,
3135                                     std::string type,
3136                                     std::string name,
3137                                     bool newCompoInst,
3138                                     int swCase,
3139                                     bool replace)
3140 {
3141   DEBTRACE("SubjectSwitch::addNode("<<catalog<<","<<compo<<","<<type<<","<<name<<","<<swCase<<","<<(int)replace<<")");
3142   SubjectNode* body = 0;
3143   if (!replace && _bodyMap.count(swCase))
3144     {
3145       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a switch case, put the nodes in a bloc"; 
3146       return body;
3147     }
3148   body = createNode(catalog, compo, type, name, newCompoInst, swCase);
3149   return body;
3150 }
3151
3152 void SubjectSwitch::removeNode(SubjectNode* son)
3153 {
3154   DEBTRACE("SubjectSwitch::removeNode("<<son->getName()<<")");
3155   if (son)
3156   {
3157     int id;
3158     bool isFound = false;
3159     map<int, SubjectNode*>::const_iterator it;
3160     for (it = _bodyMap.begin(); it != _bodyMap.end(); ++it)
3161     {
3162       if ( (*it).second == son )
3163       {
3164         isFound = true;
3165         id = (*it).first;
3166         break;
3167       }
3168     }
3169     if (isFound)
3170     {
3171       DEBTRACE("id = "<<id);
3172       _bodyMap.erase(id);
3173     }
3174   }
3175 }
3176
3177 std::map<int, SubjectNode*> SubjectSwitch::getBodyMap()
3178 {
3179   return _bodyMap;
3180 }
3181
3182 void SubjectSwitch::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
3183 {
3184   DEBTRACE("SubjectSwitch::houseKeepingAfterCutPaste");
3185   if (isCut)
3186     _bodyMap.erase(_switch->getRankOfNode(son->getNode()));
3187   else
3188     _bodyMap[_switch->getRankOfNode(son->getNode())] = son;
3189 }
3190
3191
3192 void SubjectSwitch::completeChildrenSubjectList(SubjectNode *son)
3193 {
3194   DEBTRACE("SubjectSwitch::completeChildrenSubjectList");
3195   _bodyMap[_switch->getRankOfNode(son->getNode())] = son;
3196 }
3197
3198 SubjectNode* SubjectSwitch::getChild(YACS::ENGINE::Node* node) const
3199 {
3200   SubjectNode* aChild = 0;
3201
3202   if (node)
3203   {
3204     map<int, SubjectNode*>::const_iterator it;
3205     for (it = _bodyMap.begin(); it != _bodyMap.end(); ++it)
3206       if ( (*it).second->getNode() == node )
3207       {
3208         aChild = (*it).second;
3209         break;
3210       }
3211   }
3212
3213   return aChild;
3214 }
3215
3216 bool SubjectSwitch::setSelect(std::string select)
3217 {
3218   DEBTRACE("SubjectSwitch::setSelect " << select);
3219   Proc *proc = GuiContext::getCurrent()->getProc();
3220   CommandSetSwitchSelect *command =
3221     new CommandSetSwitchSelect(proc->getChildName(getNode()), select);
3222   if (command->execute())
3223     {
3224       GuiContext::getCurrent()->getInvoc()->add(command);
3225       return true;
3226     }
3227   else delete command;
3228   return false;
3229 }
3230
3231 bool SubjectSwitch::setCase(std::string caseId, SubjectNode* snode)
3232 {
3233   DEBTRACE("SubjectSwitch::setCase " << caseId);
3234   Proc *proc = GuiContext::getCurrent()->getProc();
3235
3236   Switch* aSwitch = dynamic_cast<Switch*>(getNode());
3237   Node* node =snode->getNode();
3238   int previousRank = aSwitch->getRankOfNode(node);
3239   int newRank = atoi(caseId.c_str());
3240   if (previousRank == newRank) return true; // nothing to do.
3241
3242   CommandSetSwitchCase *command =
3243     new CommandSetSwitchCase(proc->getChildName(getNode()),
3244                              proc->getChildName(snode->getNode()),
3245                              caseId);
3246   if (command->execute())
3247     {
3248       GuiContext::getCurrent()->getInvoc()->add(command);
3249       return true;
3250     }
3251   else delete command;
3252   return false;
3253 }
3254
3255 bool SubjectSwitch::hasValue()
3256 {
3257   return true;
3258 }
3259
3260 std::string SubjectSwitch::getValue()
3261 {
3262   return _switch->edGetConditionPort()->getAsString();
3263 }
3264
3265 // ----------------------------------------------------------------------------
3266
3267 SubjectDynParaLoop::SubjectDynParaLoop(YACS::ENGINE::DynParaLoop * dynParaLoop, Subject * parent)
3268   : SubjectComposedNode(dynParaLoop, parent), _dynParaLoop(dynParaLoop)
3269 {
3270   _subjectExecNode = NULL;
3271   _subjectInitNode = NULL;
3272   _subjectFinalizeNode = NULL;
3273 }
3274
3275 SubjectDynParaLoop::~SubjectDynParaLoop()
3276 {
3277   DEBTRACE("SubjectDynParaLoop::~SubjectDynParaLoop " << getName());
3278 }
3279
3280 void SubjectDynParaLoop::recursiveUpdate(GuiEvent event, int type, Subject * son)
3281 {
3282   update(event, type, son);
3283   if (_subjectExecNode)
3284     _subjectExecNode->recursiveUpdate(event, type, son);
3285   if (_subjectInitNode)
3286     _subjectInitNode->recursiveUpdate(event, type, son);
3287   if (_subjectFinalizeNode)
3288     _subjectFinalizeNode->recursiveUpdate(event, type, son);
3289 }
3290
3291 SubjectNode * SubjectDynParaLoop::addNode(YACS::ENGINE::Catalog * catalog,
3292                                           std::string compo,
3293                                           std::string type,
3294                                           std::string name,
3295                                           bool newCompoInst)
3296 {
3297   DEBTRACE("SubjectDynParaLoop::addNode(catalog, compo, type, name)");
3298   if (_subjectExecNode)
3299     {
3300       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a loop, "
3301                                                     "put the nodes in a bloc";
3302       return NULL;
3303     }
3304   return createNode(catalog, compo, type, name, newCompoInst);
3305 }
3306
3307 void SubjectDynParaLoop::houseKeepingAfterCutPaste(bool isCut, SubjectNode * son)
3308 {
3309   if (isCut)
3310     removeNode(son);
3311   else
3312     _subjectExecNode = son;
3313 }
3314
3315 void SubjectDynParaLoop::clean(Command * command)
3316 {
3317   if (_askRegisterUndo)
3318     {
3319       _askRegisterUndo = false;
3320       registerUndoDestroy();
3321     }
3322   localclean(command);
3323   SubjectComposedNode::clean(command);
3324 }
3325
3326 void SubjectDynParaLoop::localclean(Command * command)
3327 {
3328   DEBTRACE("SubjectDynParaLoop::localClean ");
3329   if (_subjectExecNode)
3330     {
3331       DEBTRACE(_subjectExecNode->getName());
3332       erase(_subjectExecNode);
3333     }
3334   if (_subjectInitNode)
3335     {
3336       DEBTRACE(_subjectInitNode->getName());
3337       erase(_subjectInitNode);
3338     }
3339   if (_subjectFinalizeNode)
3340     {
3341       DEBTRACE(_subjectFinalizeNode->getName());
3342       erase(_subjectFinalizeNode);
3343     }
3344 }
3345
3346 void SubjectDynParaLoop::completeChildrenSubjectList(SubjectNode * son)
3347 {
3348   YASSERT(son);
3349   if (son->getNode() == _dynParaLoop->getExecNode())
3350     _subjectExecNode = son;
3351   else if (son->getNode() == _dynParaLoop->getInitNode())
3352     _subjectInitNode = son;
3353   else if (son->getNode() == _dynParaLoop->getFinalizeNode())
3354     _subjectFinalizeNode = son;
3355   else
3356     YASSERT(false);
3357 }
3358
3359 void SubjectDynParaLoop::removeNode(SubjectNode * child)
3360 {
3361   YASSERT(child);
3362   if (child == _subjectExecNode)
3363     _subjectExecNode = NULL;
3364   else if (child == _subjectInitNode)
3365     _subjectInitNode = NULL;
3366   else if (child == _subjectFinalizeNode)
3367     _subjectFinalizeNode = NULL;
3368   else
3369     YASSERT(false);
3370 }
3371
3372 SubjectNode * SubjectDynParaLoop::getChild(YACS::ENGINE::Node * node) const
3373 {
3374   return _subjectExecNode;
3375 }
3376
3377 bool SubjectDynParaLoop::setNbBranches(std::string nbBranches)
3378 {
3379   DEBTRACE("SubjectDynParaLoop::setNbBranches " << nbBranches);
3380   Proc * proc = GuiContext::getCurrent()->getProc();
3381   CommandSetForEachBranch * command =
3382     new CommandSetForEachBranch(proc->getChildName(getNode()), nbBranches);
3383   if (command->execute())
3384     {
3385       GuiContext::getCurrent()->getInvoc()->add(command);
3386       return true;
3387     }
3388   else delete command;
3389   return false;
3390 }
3391
3392 bool SubjectDynParaLoop::hasValue()
3393 {
3394   return true;
3395 }
3396
3397 std::string SubjectDynParaLoop::getValue()
3398 {
3399   return _dynParaLoop->edGetNbOfBranchesPort()->getAsString();
3400 }
3401
3402 // ----------------------------------------------------------------------------
3403
3404 SubjectForEachLoop::SubjectForEachLoop(YACS::ENGINE::ForEachLoop *forEachLoop, Subject *parent)
3405   : SubjectDynParaLoop(forEachLoop, parent), _forEachLoop(forEachLoop)
3406 {
3407   _splitter = 0;
3408 }
3409
3410 SubjectForEachLoop::~SubjectForEachLoop()
3411 {
3412   DEBTRACE("SubjectForEachLoop::~SubjectForEachLoop " << getName());
3413 }
3414
3415 void SubjectForEachLoop::clean(Command *command)
3416 {
3417   if (_askRegisterUndo)
3418     {
3419       _askRegisterUndo = false;
3420       registerUndoDestroy();
3421     }
3422   Node* aSplitterEngine = 0;
3423   if (_splitter) aSplitterEngine = _splitter->getNode();
3424
3425   localclean(command);
3426   SubjectDynParaLoop::clean(command);
3427
3428   if (_forEachLoop && aSplitterEngine)
3429     {
3430       DEBTRACE("SubjectForEachLoop::clean: remove for each loop splitter");
3431       _forEachLoop->edRemoveChild(aSplitterEngine);
3432     }
3433 }
3434
3435 void SubjectForEachLoop::localclean(Command *command)
3436 {
3437   DEBTRACE("SubjectForEachLoop::localClean ");
3438   if (_splitter)
3439     {
3440       DEBTRACE(_splitter->getName());
3441       erase(_splitter);
3442     }
3443 }
3444
3445 void SubjectForEachLoop::completeChildrenSubjectList(SubjectNode *son)
3446 {
3447   if (son && son->getName() == ForEachLoop::NAME_OF_SPLITTERNODE)
3448     _splitter = son;
3449   else
3450     SubjectDynParaLoop::completeChildrenSubjectList(son);
3451 }
3452
3453 void SubjectForEachLoop::removeNode(SubjectNode * child)
3454 {
3455   YASSERT(child);
3456   if (child->getName() == ForEachLoop::NAME_OF_SPLITTERNODE)
3457     _splitter = NULL;
3458   else {
3459     SubjectDynParaLoop::removeNode(child);
3460   }
3461 }
3462
3463 // ----------------------------------------------------------------------------
3464
3465 SubjectOptimizerLoop::SubjectOptimizerLoop(YACS::ENGINE::OptimizerLoop *optimizerLoop,
3466                                            Subject *parent)
3467   : SubjectDynParaLoop(optimizerLoop, parent), _optimizerLoop(optimizerLoop)
3468 {
3469 }
3470
3471 SubjectOptimizerLoop::~SubjectOptimizerLoop()
3472 {
3473   DEBTRACE("SubjectOptimizerLoop::~SubjectOptimizerLoop " << getName());
3474 }
3475
3476 void SubjectOptimizerLoop::clean(Command *command)
3477 {
3478   if (_askRegisterUndo)
3479     {
3480       _askRegisterUndo = false;
3481       registerUndoDestroy();
3482     }
3483   localclean(command);
3484   SubjectDynParaLoop::clean(command);
3485 }
3486
3487 void SubjectOptimizerLoop::localclean(Command *command)
3488 {
3489   DEBTRACE("SubjectOptimizerLoop::localClean ");
3490 }
3491
3492 bool SubjectOptimizerLoop::setAlgorithm(const std::string& alglib,const std::string& symbol)
3493 {
3494   DEBTRACE("SubjectOptimizerLoop::setAlgorithm " << alglib << " " << symbol);
3495   Proc *proc = GuiContext::getCurrent()->getProc();
3496   CommandSetAlgo *command = new CommandSetAlgo(proc->getChildName(getNode()), alglib, symbol);
3497   if (command->execute())
3498     {
3499       GuiContext::getCurrent()->getInvoc()->add(command);
3500       return true;
3501     }
3502   else delete command;
3503   return false;
3504 }
3505
3506 // ----------------------------------------------------------------------------
3507
3508 SubjectDataPort::SubjectDataPort(YACS::ENGINE::DataPort* port, Subject *parent)
3509   : Subject(parent), _dataPort(port)
3510 {
3511   _listSubjectLink.clear();
3512   _execValue = "";
3513 }
3514
3515 SubjectDataPort::~SubjectDataPort()
3516 {
3517   DEBTRACE("SubjectDataPort::~SubjectDataPort " << getName());
3518   if (isDestructible())
3519     {
3520       Node* node = _dataPort->getNode();
3521       YASSERT(node);
3522       ElementaryNode * father = dynamic_cast<ElementaryNode*>(node);
3523       if (father)
3524         {
3525           DEBTRACE("father->edRemovePort(_dataPort)");
3526           try
3527             {
3528               father->edRemovePort(_dataPort);
3529             }
3530           catch (YACS::Exception &e)
3531             {
3532               DEBTRACE("------------------------------------------------------------------------------");
3533               DEBTRACE("SubjectDataPort::~SubjectDataPort: father->edRemovePort: YACS exception " << e.what());
3534               DEBTRACE("------------------------------------------------------------------------------");
3535             }
3536         }
3537     }
3538 }
3539
3540 void SubjectDataPort::clean(Command *command)
3541 {
3542   if (_askRegisterUndo)
3543     {
3544       _askRegisterUndo = false;
3545       registerUndoDestroy();
3546     }
3547   localclean(command);
3548   Subject::clean(command);
3549 }
3550
3551 void SubjectDataPort::localclean(Command *command)
3552 {
3553   DEBTRACE("SubjectDataPort::localClean ");
3554   list<SubjectLink*> lsl = getListOfSubjectLink();
3555   for (list<SubjectLink*>::iterator it = lsl.begin(); it != lsl.end(); ++it)
3556     erase(*it);
3557 }
3558
3559 std::string SubjectDataPort::getName()
3560 {
3561   return _dataPort->getName();
3562 }
3563
3564 bool SubjectDataPort::setName(std::string name)
3565 {
3566   DEBTRACE("SubjectDataPort::setName " << name);
3567   Proc *proc = GuiContext::getCurrent()->getProc();
3568   string position = "";
3569   Node *node = getPort()->getNode();
3570   if (proc != dynamic_cast<Proc*>(node))
3571     position = proc->getChildName(node);
3572   else
3573     position = node->getName();
3574
3575   Command *command = 0;
3576   bool isIn = dynamic_cast<InPort*>(_dataPort);
3577   if (isIn) 
3578     command = new CommandRenameInDataPort(position, _dataPort->getName(),name, getType());
3579   else 
3580     command = new CommandRenameOutDataPort(position, _dataPort->getName(),name, getType());
3581
3582   if (command->execute())
3583     {
3584       GuiContext::getCurrent()->getInvoc()->add(command);
3585       return true;
3586     }
3587   else delete command;
3588   return false;
3589 }
3590
3591 YACS::ENGINE::DataPort* SubjectDataPort::getPort()
3592 {
3593   return _dataPort;
3594 }
3595
3596 bool SubjectDataPort::tryCreateLink(SubjectDataPort *subOutport, SubjectDataPort *subInport,bool control)
3597 {
3598   DEBTRACE("SubjectDataPort::tryCreateLink");
3599
3600   InPort *inp = dynamic_cast<InPort*>(subInport->getPort());
3601   OutPort *outp = dynamic_cast<OutPort*>(subOutport->getPort());
3602   if (outp && outp->isAlreadyLinkedWith(inp))
3603     {
3604       DEBTRACE("isAlreadyLinkedWith");
3605       GuiContext::getCurrent()->_lastErrorMessage = "Ports are already linked"; 
3606       return false;
3607     }
3608
3609   Proc *proc = GuiContext::getCurrent()->getProc();
3610
3611   string outNodePos = "";
3612   SubjectNode *sno = dynamic_cast<SubjectNode*>(subOutport->getParent());
3613   YASSERT(sno);
3614   Node *outNode = sno->getNode();
3615   outNodePos = proc->getChildName(outNode);
3616   string outportName = subOutport->getName();
3617
3618   string inNodePos = "";
3619   SubjectNode *sni = dynamic_cast<SubjectNode*>(subInport->getParent());
3620   YASSERT(sni);
3621   Node *inNode = sni->getNode();
3622   inNodePos = proc->getChildName(inNode);
3623   string inportName = subInport->getName();
3624
3625   CommandAddLink *command = new CommandAddLink(outNodePos, outportName, subOutport->getType(),
3626                                                inNodePos, inportName, subInport->getType(), control);
3627   if (command->execute())
3628     {
3629       GuiContext::getCurrent()->getInvoc()->add(command);
3630       return true;
3631     }
3632   else
3633     {
3634       delete command;
3635       return false;
3636     }
3637 }
3638
3639 /*! Generic method do nothing.
3640  *  Implementation in SubjectInputPort and SubjectOutputPort.
3641  */
3642 bool SubjectDataPort::setValue(std::string value)
3643 {
3644   return false;
3645 }
3646
3647 void SubjectDataPort::setExecValue(std::string value)
3648 {
3649   _execValue = value;
3650 }
3651
3652 std::string SubjectDataPort::getExecValue()
3653 {
3654   return _execValue;
3655 }
3656
3657 void SubjectDataPort::registerUndoDestroy()
3658 {
3659   DEBTRACE("SubjectDataPort::registerUndoDestroy");
3660   Proc *proc = GuiContext::getCurrent()->getProc();
3661   SubjectNode *sno = dynamic_cast<SubjectNode*>(getParent());
3662   YASSERT(sno);
3663   Node *node = sno->getNode();
3664   string nodeName = proc->getChildName(node);
3665   string portName = getName();
3666   ElementaryNode* father = dynamic_cast<ElementaryNode*>(node);
3667   YASSERT(father);
3668
3669   DataPort *port = getPort();
3670   TypeCode *dtyp = port->edGetType();
3671   string typeName = dtyp->name();
3672   Catalog *undoCata = GuiContext::getCurrent()->getInvoc()->getUndoCata();
3673   undoCata->_typeMap[typeName] = dtyp;
3674
3675   Command *command = 0;
3676   Command *comm2 =0;
3677   TypeOfElem elemType = getType();
3678   switch (elemType)
3679     {
3680     case INPUTPORT:
3681       command = new CommandAddInputPortFromCatalog(undoCata, typeName, nodeName, portName);
3682       {
3683         int rang = 1;
3684         int nbUp = 0;
3685         list<InputPort*> plist = father->getSetOfInputPort();
3686         list<InputPort*>::iterator pos = plist.begin();
3687         for (; (*pos) != port; pos++)
3688           rang++;
3689         nbUp = plist.size() -rang;
3690         if (nbUp)
3691           comm2 = new CommandOrderInputPorts(nodeName, portName, nbUp);
3692       }
3693       break;
3694     case OUTPUTPORT:
3695       command = new CommandAddOutputPortFromCatalog(undoCata, typeName, nodeName, portName);
3696       {
3697         int rang = 1;
3698         int nbUp = 0;
3699         list<OutputPort*> plist = father->getSetOfOutputPort();
3700         list<OutputPort*>::iterator pos = plist.begin();
3701         for (; (*pos) != port; pos++)
3702           rang++;
3703         nbUp = plist.size() -rang;
3704         if (nbUp)
3705           comm2 = new CommandOrderOutputPorts(nodeName, portName, nbUp);
3706       }
3707       break;
3708     case INPUTDATASTREAMPORT:
3709       command = new CommandAddIDSPortFromCatalog(undoCata, typeName, nodeName, portName);
3710       break;
3711     case OUTPUTDATASTREAMPORT:
3712       command = new CommandAddODSPortFromCatalog(undoCata, typeName, nodeName, portName);
3713       break;
3714     }
3715   if (command)
3716     GuiContext::getCurrent()->getInvoc()->add(command);
3717   if (comm2)
3718     GuiContext::getCurrent()->getInvoc()->add(comm2);
3719   //save links
3720   list<SubjectLink*> lsl = getListOfSubjectLink();
3721   for (list<SubjectLink*>::iterator it = lsl.begin(); it != lsl.end(); ++it)
3722     {
3723       (*it)->registerUndoDestroy();
3724     }
3725 }
3726
3727
3728 // ----------------------------------------------------------------------------
3729
3730 SubjectInputPort::SubjectInputPort(YACS::ENGINE::InputPort *port, Subject *parent)
3731   : SubjectDataPort(port, parent), _inputPort(port)
3732 {
3733   Node *node = _inputPort->getNode();
3734   if (ForLoop* forloop = dynamic_cast<ForLoop*>(node))
3735     {
3736       if (_inputPort->getName() == "nsteps") _destructible = false;
3737     }
3738   else if (WhileLoop* whileloop = dynamic_cast<WhileLoop*>(node))
3739     {
3740       if (_inputPort->getName() == "condition") _destructible = false;
3741     }
3742   else if (Switch* aSwitch = dynamic_cast<Switch*>(node))
3743     {
3744       if (_inputPort->getName() == "select") _destructible = false;
3745     }
3746   else if (ForEachLoop* foreach = dynamic_cast<ForEachLoop*>(node))
3747     {
3748       if (_inputPort->getName() == "nbBranches") _destructible = false;
3749     }
3750   else if (OptimizerLoop* optil = dynamic_cast<OptimizerLoop*>(node))
3751     {
3752       if (_inputPort->getName() == "nbBranches") _destructible = false;
3753     }
3754   else if (SplitterNode* split = dynamic_cast<SplitterNode*>(node))
3755     {
3756       if (_inputPort->getName() == "SmplsCollection") _destructible = false;
3757     }
3758
3759 }
3760
3761 SubjectInputPort::~SubjectInputPort()
3762 {
3763   DEBTRACE("SubjectInputPort::~SubjectInputPort " << getName());
3764 }
3765
3766 void SubjectInputPort::clean(Command *command)
3767 {
3768   if (_askRegisterUndo)
3769     {
3770       _askRegisterUndo = false;
3771       registerUndoDestroy();
3772     }
3773   localclean(command);
3774   SubjectDataPort::clean(command);
3775 }
3776
3777 void SubjectInputPort::localclean(Command *command)
3778 {
3779   DEBTRACE("SubjectInputPort::localClean ");
3780   if (_parent)
3781     {
3782       SubjectElementaryNode* elem = dynamic_cast<SubjectElementaryNode*>(_parent);
3783       if (elem) elem->removePort(this);
3784     }
3785 }
3786
3787 bool SubjectInputPort::setValue(std::string value)
3788 {
3789   DEBTRACE("SubjectInputPort::setValue " << value);
3790   Proc *proc = GuiContext::getCurrent()->getProc();
3791   CommandSetInPortValue *command =
3792     new CommandSetInPortValue(proc->getChildName(getPort()->getNode()), getName(), value);
3793   if (command->execute())
3794     {
3795       GuiContext::getCurrent()->getInvoc()->add(command);
3796       return true;
3797     }
3798   else delete command;
3799   return false;
3800 }
3801
3802 // ----------------------------------------------------------------------------
3803
3804 SubjectOutputPort::SubjectOutputPort(YACS::ENGINE::OutputPort *port, Subject *parent)
3805   : SubjectDataPort(port, parent), _outputPort(port)
3806 {
3807   if (DynParaLoop* dynloop = dynamic_cast<DynParaLoop*>(_outputPort->getNode()))
3808     {
3809       if (_outputPort == dynloop->edGetSamplePort()) _destructible = false;
3810     }
3811 }
3812
3813 SubjectOutputPort::~SubjectOutputPort()
3814 {
3815   DEBTRACE("SubjectOutputPort::~SubjectOutputPort " << getName());
3816 }
3817
3818 void SubjectOutputPort::clean(Command *command)
3819 {
3820   if (_askRegisterUndo)
3821     {
3822       _askRegisterUndo = false;
3823       registerUndoDestroy();
3824     }
3825   localclean(command);
3826   SubjectDataPort::clean(command);
3827 }
3828
3829 void SubjectOutputPort::localclean(Command *command)
3830 {
3831   DEBTRACE("SubjectOutputPort::localClean ");
3832   if (_parent)
3833     {
3834       SubjectElementaryNode* elem = dynamic_cast<SubjectElementaryNode*>(_parent);
3835       if (elem) elem->removePort(this);
3836     }
3837 }
3838
3839 bool SubjectOutputPort::setValue(std::string value)
3840 {
3841   DEBTRACE("SubjectOutputPort::setValue " << value);
3842   Proc *proc = GuiContext::getCurrent()->getProc();
3843   CommandSetOutPortValue *command =
3844     new CommandSetOutPortValue(proc->getChildName(getPort()->getNode()), getName(), value);
3845   if (command->execute())
3846     {
3847       GuiContext::getCurrent()->getInvoc()->add(command);
3848       return true;
3849     }
3850   else delete command;
3851   return false;
3852 }
3853
3854 // ----------------------------------------------------------------------------
3855
3856 SubjectInputDataStreamPort::SubjectInputDataStreamPort(YACS::ENGINE::InputDataStreamPort *port,
3857                                                        Subject *parent)
3858   : SubjectDataPort(port, parent), _inputDataStreamPort(port)
3859 {
3860 }
3861
3862 SubjectInputDataStreamPort::~SubjectInputDataStreamPort()
3863 {
3864   DEBTRACE("SubjectInputDataStreamPort::~SubjectInputDataStreamPort " << getName());
3865 }
3866
3867 std::map<std::string, std::string> SubjectInputDataStreamPort::getProperties()
3868 {
3869   return _inputDataStreamPort->getProperties();
3870 }
3871
3872 std::vector<std::string> SubjectInputDataStreamPort::knownProperties()
3873 {
3874   std::vector<std::string> props;
3875   props.push_back("StorageLevel");
3876   //props.push_back("DependencyType");
3877   props.push_back("DateCalSchem");
3878   props.push_back("Alpha");
3879   props.push_back("DeltaT");
3880   props.push_back("InterpolationSchem");
3881   props.push_back("ExtrapolationSchem");
3882   return props;
3883 }
3884
3885 bool SubjectInputDataStreamPort::setProperties(std::map<std::string, std::string> properties)
3886 {
3887   Proc *proc = GuiContext::getCurrent()->getProc();
3888   CommandSetDSPortProperties *command =
3889     new CommandSetDSPortProperties(proc->getChildName(getPort()->getNode()), getName(), true, properties);
3890   if (command->execute())
3891     {
3892       GuiContext::getCurrent()->getInvoc()->add(command);
3893       return true;
3894     }
3895   else delete command;
3896   return false;
3897 }
3898
3899 void SubjectInputDataStreamPort::clean(Command *command)
3900 {
3901   if (_askRegisterUndo)
3902     {
3903       _askRegisterUndo = false;
3904       registerUndoDestroy();
3905     }
3906   localclean(command);
3907   SubjectDataPort::clean(command);
3908 }
3909
3910 void SubjectInputDataStreamPort::localclean(Command *command)
3911 {
3912   DEBTRACE("SubjectInputDataStreamPort::localClean ");
3913 }
3914
3915 void SubjectInputDataStreamPort::registerUndoDestroy()
3916 {
3917   DEBTRACE("SubjectInputDataStreamPort::registerUndoDestroy");
3918   SubjectDataPort::registerUndoDestroy();
3919   map<string,string> properties = getProperties();
3920   if (properties.empty())
3921     return;
3922   Proc *proc = GuiContext::getCurrent()->getProc();
3923   SubjectNode *sno = dynamic_cast<SubjectNode*>(getParent());
3924   YASSERT(sno);
3925   Node *node = sno->getNode();
3926   string nodeName = proc->getChildName(node);
3927   string portName = getName();
3928   Command *command = new CommandSetDSPortProperties(nodeName, portName, true, properties);
3929   GuiContext::getCurrent()->getInvoc()->add(command);
3930 }
3931
3932 // ----------------------------------------------------------------------------
3933
3934 SubjectOutputDataStreamPort::SubjectOutputDataStreamPort(YACS::ENGINE::OutputDataStreamPort *port,
3935                                                          Subject *parent)
3936   : SubjectDataPort(port, parent), _outputDataStreamPort(port)
3937 {
3938 }
3939
3940 SubjectOutputDataStreamPort::~SubjectOutputDataStreamPort()
3941 {
3942   DEBTRACE("SubjectOutputDataStreamPort::~SubjectOutputDataStreamPort " << getName());
3943 }
3944
3945 std::map<std::string, std::string> SubjectOutputDataStreamPort::getProperties()
3946 {
3947   return _outputDataStreamPort->getProperties();
3948 }
3949
3950 bool SubjectOutputDataStreamPort::setProperties(std::map<std::string, std::string> properties)
3951 {
3952   Proc *proc = GuiContext::getCurrent()->getProc();
3953   CommandSetDSPortProperties *command =
3954     new CommandSetDSPortProperties(proc->getChildName(getPort()->getNode()), getName(), false, properties);
3955   if (command->execute())
3956     {
3957       GuiContext::getCurrent()->getInvoc()->add(command);
3958       return true;
3959     }
3960   else delete command;
3961   return false;
3962 }
3963
3964 void SubjectOutputDataStreamPort::clean(Command *command)
3965 {
3966   if (_askRegisterUndo)
3967     {
3968       _askRegisterUndo = false;
3969       registerUndoDestroy();
3970     }
3971   localclean(command);
3972   SubjectDataPort::clean(command);
3973 }
3974
3975 void SubjectOutputDataStreamPort::localclean(Command *command)
3976 {
3977   DEBTRACE("SubjectOutputDataStreamPort::localClean ");
3978 }
3979
3980 void SubjectOutputDataStreamPort::registerUndoDestroy()
3981 {
3982   DEBTRACE("SubjectOutputDataStreamPort::registerUndoDestroy");
3983   SubjectDataPort::registerUndoDestroy();
3984   map<string,string> properties = getProperties();
3985   if (properties.empty())
3986     return;
3987   Proc *proc = GuiContext::getCurrent()->getProc();
3988   SubjectNode *sno = dynamic_cast<SubjectNode*>(getParent());
3989   YASSERT(sno);
3990   Node *node = sno->getNode();
3991   string nodeName = proc->getChildName(node);
3992   string portName = getName();
3993   Command *command = new CommandSetDSPortProperties(nodeName, portName, false, properties);
3994   GuiContext::getCurrent()->getInvoc()->add(command);
3995 }
3996
3997 // ----------------------------------------------------------------------------
3998
3999 SubjectLink::SubjectLink(SubjectNode* subOutNode,
4000                          SubjectDataPort* outPort,
4001                          SubjectNode* subInNode,
4002                          SubjectDataPort* inPort,
4003                          Subject *parent)
4004   : Subject(parent),
4005     _subOutNode(subOutNode), _outPort(outPort), _subInNode(subInNode), _inPort(inPort)
4006 {
4007   _name = "";
4008   ComposedNode *cla = ComposedNode::getLowestCommonAncestor(_subOutNode->getNode()->getFather(),
4009                                                             _subInNode->getNode()->getFather());
4010   DEBTRACE(_subOutNode->getName() << "." << _outPort->getName());
4011   DEBTRACE(_subInNode->getName() << "." << _inPort->getName());
4012   DEBTRACE(cla->getName());
4013   _name += cla->getChildName(_subOutNode->getNode());
4014   _name += "." + _outPort->getName();
4015   _name += "->";
4016   _name += cla->getChildName(_subInNode->getNode());
4017   _name += "." + _inPort->getName();
4018   DEBTRACE("SubjectLink::SubjectLink " << _name);
4019 }
4020
4021 SubjectLink::~SubjectLink()
4022 {
4023   DEBTRACE("SubjectLink::~SubjectLink " << getName());
4024   _inPort->update(UPDATE,DATALINK,_outPort);
4025   _outPort->update(UPDATE,DATALINK,_inPort);
4026 }
4027
4028 void SubjectLink::clean(Command *command)
4029 {
4030   if (_askRegisterUndo)
4031     {
4032       _askRegisterUndo = false;
4033       registerUndoDestroy();
4034     }
4035   localclean(command);
4036   Subject::clean(command);
4037 }
4038
4039 void SubjectLink::localclean(Command *command)
4040 {
4041   DEBTRACE("SubjectLink::localClean ");
4042   if (_parent)
4043     {
4044       DEBTRACE("clean link: " << _parent->getName() << " " << getName());
4045       SubjectComposedNode* father = dynamic_cast<SubjectComposedNode*>(_parent);
4046       YASSERT(father);
4047       father->removeLink(this); // --- clean subjects first
4048       _cla = dynamic_cast<ComposedNode*>(father->getNode());
4049       YASSERT(_cla);
4050       _outp = dynamic_cast<OutPort*>(_outPort->getPort());
4051       YASSERT(_outp);
4052       _inp = dynamic_cast<InPort*>(_inPort->getPort());
4053       YASSERT(_inp);
4054       if (isDestructible())
4055         _cla->edRemoveLink(_outp, _inp);
4056     }
4057 }
4058
4059 std::string SubjectLink::getName()
4060 {
4061   return _name;
4062 }
4063
4064 std::map<std::string, std::string> SubjectLink::getProperties()
4065 {
4066   return getSubjectInPort()->getProperties();
4067 }
4068
4069 std::vector<std::string> SubjectLink::knownProperties()
4070 {
4071   return getSubjectInPort()->knownProperties();
4072 }
4073
4074 bool SubjectLink::setProperties(std::map<std::string, std::string> properties)
4075 {
4076   Proc *proc = GuiContext::getCurrent()->getProc();
4077   CommandSetLinkProperties *command =
4078     new CommandSetLinkProperties(proc->getChildName(getSubjectOutPort()->getPort()->getNode()), getSubjectOutPort()->getName(), 
4079                                  proc->getChildName(getSubjectInPort()->getPort()->getNode()), getSubjectInPort()->getName(), 
4080                                  properties);
4081   if (command->execute())
4082     {
4083       GuiContext::getCurrent()->getInvoc()->add(command);
4084       return true;
4085     }
4086   else delete command;
4087   return false;
4088 }
4089
4090 void SubjectLink::registerUndoDestroy()
4091 {
4092   DEBTRACE("SubjectLink::registerUndoDestroy");
4093   Proc *proc = GuiContext::getCurrent()->getProc();
4094   Node *outn = getSubjectOutNode()->getNode();
4095   Node *inn = getSubjectInNode()->getNode();
4096   DataPort *outp = getSubjectOutPort()->getPort();
4097   DataPort *inp = getSubjectInPort()->getPort();
4098   CommandAddLink *command = new CommandAddLink(proc->getChildName(outn),
4099                                                outp->getName(),
4100                                                getSubjectOutPort()->getType(),
4101                                                proc->getChildName(inn),
4102                                                inp->getName(),
4103                                                getSubjectInPort()->getType(),
4104                                                false);
4105   GuiContext::getCurrent()->getInvoc()->add(command);
4106
4107   map<string, string> properties = getProperties();
4108   if (properties.empty())
4109     return;
4110
4111   CommandSetLinkProperties *command2 = new CommandSetLinkProperties(proc->getChildName(outn),
4112                                                                     outp->getName(),
4113                                                                     proc->getChildName(inn),
4114                                                                     inp->getName(),
4115                                                                     properties);
4116   GuiContext::getCurrent()->getInvoc()->add(command2); 
4117 }
4118
4119 // ----------------------------------------------------------------------------
4120
4121 SubjectControlLink::SubjectControlLink(SubjectNode* subOutNode,
4122                                        SubjectNode* subInNode,
4123                                        Subject *parent)
4124   : Subject(parent),
4125     _subOutNode(subOutNode), _subInNode(subInNode)
4126 {
4127   _name = "";
4128   ComposedNode *cla = ComposedNode::getLowestCommonAncestor(_subOutNode->getNode()->getFather(),
4129                                                             _subInNode->getNode()->getFather());
4130   DEBTRACE(_subOutNode->getName());
4131   DEBTRACE(_subInNode->getName());
4132   DEBTRACE(cla->getName());
4133   _name += cla->getChildName(_subOutNode->getNode());
4134   _name += "-->>";
4135   _name += cla->getChildName(_subInNode->getNode());
4136   DEBTRACE("SubjectControlLink::SubjectControlLink " << _name);
4137 }
4138
4139 SubjectControlLink::~SubjectControlLink()
4140 {
4141   DEBTRACE("SubjectControlLink::~SubjectControlLink " << getName());
4142   if (isDestructible())
4143     {
4144       try
4145         {
4146
4147           _cla->edRemoveCFLink(_subOutNode->getNode(), _subInNode->getNode());
4148         }
4149       catch (YACS::Exception &e)
4150         {
4151           DEBTRACE("------------------------------------------------------------------------------");
4152           DEBTRACE("SubjectControlLink::~SubjectControlLink: edRemoveLink YACS exception " << e.what());
4153           DEBTRACE("------------------------------------------------------------------------------");
4154         }
4155     }
4156 }
4157
4158 void SubjectControlLink::clean(Command *command)
4159 {
4160   if (_askRegisterUndo)
4161     {
4162       _askRegisterUndo = false;
4163       registerUndoDestroy();
4164     }
4165   localclean(command);
4166   Subject::clean(command);
4167 }
4168
4169 void SubjectControlLink::localclean(Command *command)
4170 {
4171   DEBTRACE("SubjectControlLink::localClean ");
4172   if (_parent)
4173     {
4174       DEBTRACE("clean control link: " << _parent->getName() << " " << getName());
4175       SubjectComposedNode* father = dynamic_cast<SubjectComposedNode*>(_parent);
4176       YASSERT(father);
4177       father->removeControlLink(this); // --- clean subjects first
4178       _cla = dynamic_cast<ComposedNode*>(father->getNode());
4179       YASSERT(_cla);
4180     }
4181 }
4182
4183 std::string SubjectControlLink::getName()
4184 {
4185   return _name;
4186 }
4187
4188 void SubjectControlLink::registerUndoDestroy()
4189 {
4190   DEBTRACE("SubjectControlLink::registerUndoDestroy");
4191   Proc *proc = GuiContext::getCurrent()->getProc();
4192   Node *outn = getSubjectOutNode()->getNode();
4193   Node *inn = getSubjectInNode()->getNode();
4194   CommandAddControlLink *command = new CommandAddControlLink(proc->getChildName(outn),
4195                                                              proc->getChildName(inn));
4196   GuiContext::getCurrent()->getInvoc()->add(command);
4197 }
4198
4199 // ----------------------------------------------------------------------------
4200
4201 SubjectComponent::SubjectComponent(YACS::ENGINE::ComponentInstance* component, Subject *parent)
4202   : Subject(parent), _compoInst(component)
4203 {
4204   _compoInst->incrRef();
4205   _subRefContainer = 0;
4206   _subServiceSet.clear();
4207   _subReferenceMap.clear();
4208 }
4209
4210 SubjectComponent::~SubjectComponent()
4211 {
4212   Proc* aProc = GuiContext::getCurrent()->getProc();
4213   if ( aProc )
4214   {
4215     aProc->componentInstanceMap.erase(_compoInst->getInstanceName());
4216     GuiContext::getCurrent()->_mapOfSubjectComponent.erase(_compoInst);
4217   }
4218   _compoInst->decrRef();
4219 }
4220
4221 void SubjectComponent::clean(Command *command)
4222 {
4223   if (_askRegisterUndo)
4224     {
4225       _askRegisterUndo = false;
4226       registerUndoDestroy();
4227     }
4228   localclean(command);
4229   Subject::clean(command);
4230 }
4231
4232 void SubjectComponent::localclean(Command *command)
4233 {
4234   DEBTRACE("SubjectComponent::localClean " << this);
4235   Proc* aProc = GuiContext::getCurrent()->getProc();
4236   if ( aProc )
4237   {
4238     std::map<Node*, SubjectNode*>::iterator it = GuiContext::getCurrent()->_mapOfSubjectNode.begin();
4239     std::list<SubjectNode*> services;
4240     for ( ; it!=GuiContext::getCurrent()->_mapOfSubjectNode.end(); it++ )
4241       {
4242         if(ServiceNode* service=dynamic_cast<ServiceNode*>((*it).first))
4243           {
4244             if ( service->getComponent() == _compoInst )
4245               {
4246                 services.push_back((*it).second);
4247               }
4248           }
4249       }
4250     while(!services.empty())
4251       {
4252         SubjectNode* son=services.front();
4253         services.pop_front();
4254         Subject* parent=son->getParent();
4255 //         parent->update(REMOVE,son->getType(),son);
4256         parent->erase(son);
4257         parent->update(REMOVE,0,0);
4258       }
4259       
4260     Container* container = _compoInst->getContainer();
4261     if (!container) return;
4262     SubjectContainerBase *subContainer(0);
4263     YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(container));
4264     subContainer = GuiContext::getCurrent()->_mapOfSubjectContainer[container];
4265     subContainer->removeSubComponentFromSet(this);
4266   }
4267 }
4268
4269 std::string SubjectComponent::getName()
4270 {
4271   return _compoInst->getInstanceName();
4272 }
4273
4274 std::pair<std::string, int> SubjectComponent::getKey()
4275 {
4276   std::pair<std::string, int> key = std::pair<std::string, int>(_compoInst->getCompoName(), _compoInst->getNumId());
4277   return key;
4278 }
4279
4280 YACS::ENGINE::ComponentInstance* SubjectComponent::getComponent() const
4281 {
4282   return _compoInst;
4283 }
4284
4285 /*!
4286  *  When loading scheme from file, get the container associated to the component, if any,
4287  *  and create the corresponding subject.
4288  */
4289 void SubjectComponent::setContainer()
4290 {
4291   DEBTRACE("SubjectComponent::setContainer " << getName());
4292   Container* container = _compoInst->getContainer();
4293   if (container)
4294     {
4295       SubjectContainerBase *subContainer;
4296       if (GuiContext::getCurrent()->_mapOfSubjectContainer.count(container))
4297         subContainer = GuiContext::getCurrent()->_mapOfSubjectContainer[container];
4298       else
4299         subContainer = 
4300           GuiContext::getCurrent()->getSubjectProc()->addSubjectContainer(container, container->getName());
4301       addSubjectReference(subContainer);
4302       if (_subRefContainer)
4303         subContainer->moveComponent(_subRefContainer);
4304       else
4305         _subRefContainer = subContainer->attachComponent(this);
4306       notifyServicesChange(ASSOCIATE, CONTAINER, subContainer);
4307     }
4308 }
4309
4310 bool SubjectComponent::associateToContainer(SubjectContainerBase *subcont)
4311 {
4312   DEBTRACE("SubjectComponent::associateToContainer " << getName() << " " << subcont->getName());
4313   CommandAssociateComponentToContainer *command =
4314     new CommandAssociateComponentToContainer(_compoInst->getInstanceName(), subcont->getName());
4315   if (command->execute())
4316     {
4317       if (!GuiContext::getCurrent()->isLoading()) // do not register command when loading a schema
4318         GuiContext::getCurrent()->getInvoc()->add(command);
4319       else delete command;
4320       return true;
4321     }
4322   else delete command;
4323   return false;
4324 }
4325
4326 SubjectReference* SubjectComponent::attachService(SubjectServiceNode* service)
4327 {
4328   DEBTRACE("SubjectComponent::attachService");
4329   SubjectReference *son = new SubjectReference(service, this);
4330   _subServiceSet.insert(service);
4331   _subReferenceMap[service] = son;
4332   update(ADDCHILDREF, SALOMENODE, son);
4333   return son;
4334 }
4335
4336 void SubjectComponent::detachService(SubjectServiceNode* service)
4337 {
4338   DEBTRACE("SubjectComponent::detachService");
4339   YASSERT(_subReferenceMap.count(service));
4340   SubjectReference *reference = _subReferenceMap[service];
4341   update(REMOVECHILDREF, SALOMENODE, reference);
4342   _subServiceSet.erase(service);
4343   _subReferenceMap.erase(service);
4344   service->removeSubRefComponent();
4345   erase(reference);
4346 }
4347
4348 void SubjectComponent::moveService(SubjectReference* reference)
4349 {
4350   DEBTRACE("SubjectComponent::moveService");
4351   SubjectComponent* oldcomp = dynamic_cast<SubjectComponent*>(reference->getParent());
4352   YASSERT(oldcomp);
4353
4354   SubjectServiceNode* service = dynamic_cast<SubjectServiceNode*>(reference->getReference());
4355   oldcomp->removeSubServiceFromSet(service);
4356   _subServiceSet.insert(service);
4357   _subReferenceMap[service] = reference;
4358   oldcomp->update(CUT, SALOMENODE, reference);
4359   reference->reparent(this);
4360   update(PASTE, SALOMENODE, reference);
4361   if (!oldcomp->hasServices())
4362     Subject::erase(oldcomp);
4363 }
4364
4365 void SubjectComponent::removeSubServiceFromSet(SubjectServiceNode *service)
4366 {
4367   DEBTRACE("SubjectComponent::removeSubServiceFromSet " << getName() << " " << service->getName());
4368   _subServiceSet.erase(service);
4369   _subReferenceMap.erase(service);
4370 }
4371
4372 void SubjectComponent::notifyServicesChange(GuiEvent event, int type, Subject* son)
4373 {
4374   DEBTRACE("SubjectComponent::notifyServicesChange");
4375   set<SubjectServiceNode*>::iterator it = _subServiceSet.begin();
4376   for(; it != _subServiceSet.end(); ++it)
4377     {
4378       (*it)->update(event, type, son);
4379     }
4380 }
4381
4382 bool SubjectComponent::setProperties(std::map<std::string, std::string> properties)
4383 {
4384   CommandSetComponentInstanceProperties *command = new CommandSetComponentInstanceProperties(getName(), properties);
4385   if (command->execute())
4386     {
4387       GuiContext::getCurrent()->getInvoc()->add(command);
4388       return true;
4389     }
4390   else delete command;
4391   return false;
4392 }
4393
4394 std::map<std::string, std::string> SubjectComponent::getProperties()
4395 {
4396   return _compoInst->getProperties();
4397 }
4398
4399 // ----------------------------------------------------------------------------
4400
4401 SubjectContainerBase *SubjectContainerBase::New(YACS::ENGINE::Container* container, Subject *parent)
4402 {
4403   if(!container)
4404     return 0;
4405   if(!dynamic_cast<YACS::ENGINE::HomogeneousPoolContainer *>(container))
4406     return new SubjectContainer(container,parent);
4407   else
4408     return new SubjectHPContainer(dynamic_cast<YACS::ENGINE::HomogeneousPoolContainer *>(container),parent);
4409 }
4410
4411 SubjectContainerBase::SubjectContainerBase(YACS::ENGINE::Container* container, Subject *parent):Subject(parent), _container(container)
4412 {
4413   _subComponentSet.clear();
4414   _subReferenceMap.clear();
4415 }
4416
4417 SubjectContainerBase::~SubjectContainerBase()
4418 {
4419   DEBTRACE("SubjectContainerBase::~SubjectContainerBase");
4420   Proc* aProc = GuiContext::getCurrent()->getProc();
4421   if ( aProc )
4422   {
4423     map<ComponentInstance*,SubjectComponent*> mapOfSubjectComponentCpy
4424       = GuiContext::getCurrent()->_mapOfSubjectComponent;
4425     map<ComponentInstance*,SubjectComponent*>::iterator it = mapOfSubjectComponentCpy.begin();
4426     for ( ; it!=mapOfSubjectComponentCpy.end(); it++ )
4427       if ( (*it).first && (*it).first->getContainer() == _container )
4428       {
4429         (*it).first->setContainer(0);
4430         GuiContext::getCurrent()->getSubjectProc()->destroy((*it).second);
4431       }
4432
4433     GuiContext::getCurrent()->_mapOfSubjectContainer.erase(_container);
4434     aProc->removeContainer(_container);
4435   }
4436 }
4437
4438 std::map<std::string, std::string> SubjectContainerBase::getProperties()
4439 {
4440   return _container->getProperties();
4441 }
4442
4443 bool SubjectContainerBase::setProperties(std::map<std::string, std::string> properties)
4444 {
4445   CommandSetContainerProperties *command(new CommandSetContainerProperties(getName(), properties));
4446   if (command->execute())
4447     {
4448       GuiContext::getCurrent()->getInvoc()->add(command);
4449       return true;
4450     }
4451   else
4452     delete command;
4453   return false;
4454 }
4455
4456 bool SubjectContainerBase::setName(std::string name)
4457 {
4458   DEBTRACE("SubjectContainer::setName " << name);
4459   if (name == getName())
4460     return true;
4461   CommandRenameContainer* command = new CommandRenameContainer(getName(), name);
4462   if (command->execute())
4463     {
4464       GuiContext::getCurrent()->getInvoc()->add(command);
4465       return true;
4466     }
4467   else delete command;
4468   return false;
4469 }
4470
4471 SubjectReference* SubjectContainerBase::attachComponent(SubjectComponent* component)
4472 {
4473   DEBTRACE("SubjectContainer::attachComponent");
4474   SubjectReference *son = new SubjectReference(component, this);
4475   _subComponentSet.insert(component);
4476   _subReferenceMap[component] = son;
4477   update(ADDCHILDREF, COMPONENT, son);
4478   return son;
4479 }
4480
4481 void SubjectContainerBase::detachComponent(SubjectComponent* component)
4482 {
4483   DEBTRACE("SubjectContainer::detachComponent");
4484   YASSERT(_subReferenceMap.count(component));
4485   SubjectReference *reference = _subReferenceMap[component];
4486   update(REMOVECHILDREF, PYTHONNODE, reference);
4487   _subComponentSet.erase(component);
4488   _subReferenceMap.erase(component);
4489   erase(reference);
4490 }
4491
4492 void SubjectContainerBase::moveComponent(SubjectReference* reference)
4493 {
4494   DEBTRACE("SubjectContainer::moveComponent");
4495   SubjectContainer* oldcont = dynamic_cast<SubjectContainer*>(reference->getParent());
4496   YASSERT(oldcont);
4497   SubjectComponent* component = dynamic_cast<SubjectComponent*>(reference->getReference());
4498   _subComponentSet.insert(component);
4499   _subReferenceMap[component] = reference;
4500   oldcont->removeSubComponentFromSet(component);
4501   oldcont->update(CUT, COMPONENT, reference);
4502   reference->reparent(this);
4503   update(PASTE, COMPONENT, reference);
4504 }
4505
4506 void SubjectContainerBase::removeSubComponentFromSet(SubjectComponent *component)
4507 {
4508   DEBTRACE("SubjectContainer::removeSubComponentFromSet");
4509   _subComponentSet.erase(component);
4510   _subReferenceMap.erase(component);
4511 }
4512
4513 void SubjectContainerBase::notifyComponentsChange(GuiEvent event, int type, Subject* son)
4514 {
4515   DEBTRACE("SubjectContainer::notifyComponentsChange");
4516   set<SubjectComponent*>::iterator it = _subComponentSet.begin();
4517   for(; it != _subComponentSet.end(); ++it)
4518     {
4519       (*it)->update(event, type, son);
4520       (*it)->notifyServicesChange(event, type, son);
4521     }
4522 }
4523
4524 void SubjectContainerBase::clean(Command *command)
4525 {
4526   if (_askRegisterUndo)
4527     {
4528       _askRegisterUndo = false;
4529       registerUndoDestroy();
4530     }
4531   localclean(command);
4532   Subject::clean(command);
4533 }
4534
4535 void SubjectContainerBase::localclean(Command *command)
4536 {
4537   DEBTRACE("SubjectContainerBase::localClean ");
4538   Proc* aProc = GuiContext::getCurrent()->getProc();
4539   if ( aProc )
4540   {
4541     SubjectComponent* compo;
4542     map<ComponentInstance*,SubjectComponent*>::iterator it = GuiContext::getCurrent()->_mapOfSubjectComponent.begin();
4543     std::list<SubjectComponent*> compos;
4544     for ( ; it!=GuiContext::getCurrent()->_mapOfSubjectComponent.end(); it++ )
4545       if ( (*it).first && (*it).first->getContainer() == _container )
4546       {
4547         compo=(*it).second;
4548         (*it).first->setContainer(0);
4549         compos.push_back((*it).second);
4550       }
4551     while(!compos.empty())
4552       {
4553         compo=compos.front();
4554         compos.pop_front();
4555         GuiContext::getCurrent()->getSubjectProc()->update(REMOVE,compo->getType(),compo);
4556         GuiContext::getCurrent()->getSubjectProc()->erase(compo);
4557       }
4558   }
4559 }
4560
4561 std::string SubjectContainerBase::getName()
4562 {
4563   return _container->getName();
4564 }
4565
4566 // ----------------------------------------------------------------------------
4567
4568 SubjectContainer::SubjectContainer(YACS::ENGINE::Container *container, Subject *parent):SubjectContainerBase(container,parent)
4569 {
4570 }
4571
4572 void SubjectContainer::registerUndoDestroy()
4573 {
4574   DEBTRACE("SubjectContainer::registerUndoDestroy");
4575   Command *command = new CommandAddContainer(getName(),"");
4576   GuiContext::getCurrent()->getInvoc()->add(command);
4577 }
4578
4579 // ----------------------------------------------------------------------------
4580
4581 SubjectHPContainer::SubjectHPContainer(YACS::ENGINE::HomogeneousPoolContainer *container, Subject *parent):SubjectContainerBase(container,parent)
4582 {
4583 }
4584
4585 YACS::ENGINE::Container *SubjectHPContainer::getContainer() const
4586 {
4587   if(!_container)
4588     return 0;
4589   else
4590     {
4591       YACS::ENGINE::HomogeneousPoolContainer *ret(dynamic_cast<YACS::ENGINE::HomogeneousPoolContainer *>(_container));
4592       if(!ret)
4593         throw Exception("Invalid container type in SubjectHPContainer !");
4594       return ret;
4595     }
4596 }
4597
4598 void SubjectHPContainer::registerUndoDestroy()
4599 {
4600   DEBTRACE("SubjectHPContainer::registerUndoDestroy");
4601   Command *command = new CommandAddHPContainer(getName(),"");
4602   GuiContext::getCurrent()->getInvoc()->add(command);
4603 }
4604
4605 // ----------------------------------------------------------------------------
4606
4607 SubjectDataType::SubjectDataType(YACS::ENGINE::TypeCode *typeCode, Subject *parent, std::string alias)
4608   : Subject(parent), _typeCode(typeCode), _alias(alias)
4609 {
4610 }
4611
4612 SubjectDataType::~SubjectDataType()
4613 {
4614 }
4615
4616 void SubjectDataType::clean(Command *command)
4617 {
4618   if (_askRegisterUndo)
4619     {
4620       _askRegisterUndo = false;
4621       registerUndoDestroy();
4622     }
4623   localclean(command);
4624   Subject::clean(command);
4625 }
4626
4627 void SubjectDataType::localclean(Command *command)
4628 {
4629   DEBTRACE("SubjectDataType::localClean ");
4630 }
4631
4632 std::string SubjectDataType::getName()
4633 {
4634   return _typeCode->name();
4635 }
4636
4637 std::string SubjectDataType::getAlias()
4638 {
4639   return _alias;
4640 }
4641
4642 YACS::ENGINE::TypeCode* SubjectDataType::getTypeCode()
4643 {
4644   return _typeCode;
4645 }
4646
4647 // ----------------------------------------------------------------------------