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