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