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