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