Salome HOME
Merge branch V7_3_1_BR
[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;
2429                     if(cont->isAttachedOnCloning())
2430                       {
2431                         cont->dettachOnCloning();
2432                         newcont=cont->clone();
2433                         cont->attachOnCloning();
2434                         newcont->attachOnCloning();
2435                       }
2436                     else
2437                       newcont=cont->clone();
2438
2439                     proc->containerMap[cont->getName()]=newcont;
2440                     instance->setContainer(newcont);
2441                     GuiContext::getCurrent()->getSubjectProc()->addSubjectContainer(newcont, newcont->getName());
2442                   }
2443                 else
2444                   {
2445                     if(cont != proc->containerMap[cont->getName()])
2446                       {
2447                         //the associated container is not the same as the one in containerMap: use the containerMap one
2448                         instance->setContainer(proc->containerMap[cont->getName()]);
2449                       }
2450                   }
2451             }
2452           subCompo = GuiContext::getCurrent()->getSubjectProc()->addSubjectComponent(instance);
2453         }
2454       else
2455         {
2456           DEBTRACE("SubjectServiceNode::setComponent : get already created subject for compo = " <<compo.c_str());
2457           subCompo = GuiContext::getCurrent()->_mapOfSubjectComponent[instance];
2458         }       
2459       YASSERT(subCompo);
2460       addSubjectReference(subCompo);
2461       if (_subRefComponent)
2462         subCompo->moveService(_subRefComponent);
2463       else
2464         _subRefComponent = subCompo->attachService(this);
2465     }
2466 }
2467
2468 bool SubjectServiceNode::associateToComponent(SubjectComponent *subcomp)
2469 {
2470   DEBTRACE("SubjectServiceNode::associateToComponent " << getName() << " " << subcomp->getName());
2471   SubjectReference* oldSReference = _subjectReference;
2472   string aName = GuiContext::getCurrent()->getProc()->getChildName(_serviceNode);
2473   CommandAssociateServiceToComponent *command =
2474     new CommandAssociateServiceToComponent(aName, subcomp->getName());
2475   if (command->execute())
2476     {
2477       GuiContext::getCurrent()->getInvoc()->add(command);
2478       return true;
2479     }
2480   else delete command;
2481   return false;
2482 }
2483
2484 void SubjectServiceNode::addSubjectReference(Subject *ref)
2485 {
2486   DEBTRACE("Subject::addSubjectReference " << getName() << " " << ref->getName());
2487   SubjectReference *son = new SubjectReference(ref, this);
2488   _subjectReference = son;
2489   update(ADDREF, 0, son);
2490 }
2491
2492 SubjectReference* SubjectServiceNode::getSubjectReference()
2493 {
2494   return _subjectReference;
2495 }
2496
2497 // ----------------------------------------------------------------------------
2498
2499 SubjectPythonNode::SubjectPythonNode(YACS::ENGINE::PythonNode *pythonNode, Subject *parent)
2500   : SubjectInlineNode(pythonNode, parent), _pythonNode(pythonNode)
2501 {
2502 }
2503
2504 SubjectPythonNode::~SubjectPythonNode()
2505 {
2506   DEBTRACE("SubjectPythonNode::~SubjectPythonNode " << getName());
2507 }
2508
2509 void SubjectPythonNode::clean(Command *command)
2510 {
2511   if (_askRegisterUndo)
2512     {
2513       _askRegisterUndo = false;
2514       registerUndoDestroy();
2515     }
2516   localclean(command);
2517   SubjectInlineNode::clean(command);
2518 }
2519
2520 void SubjectPythonNode::localclean(Command *command)
2521 {
2522   DEBTRACE("SubjectPythonNode::localClean ");
2523 }
2524
2525
2526 // ----------------------------------------------------------------------------
2527
2528 SubjectPyFuncNode::SubjectPyFuncNode(YACS::ENGINE::PyFuncNode *pyFuncNode, Subject *parent)
2529   : SubjectInlineNode(pyFuncNode, parent), _pyFuncNode(pyFuncNode)
2530 {
2531 }
2532
2533 SubjectPyFuncNode::~SubjectPyFuncNode()
2534 {
2535   DEBTRACE("SubjectPyFuncNode::~SubjectPyFuncNode " << getName());
2536 }
2537
2538 bool SubjectPyFuncNode::setFunctionName(std::string funcName)
2539 {
2540   Proc *proc = GuiContext::getCurrent()->getProc();
2541   CommandSetFuncNodeFunctionName *command =
2542     new CommandSetFuncNodeFunctionName(proc->getChildName(_node), funcName);
2543   if (command->execute())
2544     {
2545       GuiContext::getCurrent()->getInvoc()->add(command);
2546       return true;
2547     }
2548   else delete command;
2549   return false;
2550 }
2551
2552 void SubjectPyFuncNode::clean(Command *command)
2553 {
2554   if (_askRegisterUndo)
2555     {
2556       _askRegisterUndo = false;
2557       registerUndoDestroy();
2558     }
2559   localclean(command);
2560   SubjectInlineNode::clean(command);
2561 }
2562
2563 void SubjectPyFuncNode::localclean(Command *command)
2564 {
2565   DEBTRACE("SubjectPyFuncNode::localClean ");
2566 }
2567
2568 // ----------------------------------------------------------------------------
2569
2570 SubjectCORBANode::SubjectCORBANode(YACS::ENGINE::CORBANode *corbaNode, Subject *parent)
2571   : SubjectServiceNode(corbaNode, parent), _corbaNode(corbaNode)
2572 {
2573 }
2574
2575 SubjectCORBANode::~SubjectCORBANode()
2576 {
2577   DEBTRACE("SubjectCORBANode::~SubjectCORBANode " << getName());
2578 }
2579
2580 void SubjectCORBANode::clean(Command *command)
2581 {
2582   if (_askRegisterUndo)
2583     {
2584       _askRegisterUndo = false;
2585       registerUndoDestroy();
2586     }
2587   localclean(command);
2588   SubjectServiceNode::clean(command);
2589 }
2590
2591 void SubjectCORBANode::localclean(Command *command)
2592 {
2593   DEBTRACE("SubjectCORBANode::localClean ");
2594 }
2595
2596
2597 // ----------------------------------------------------------------------------
2598
2599 SubjectCppNode::SubjectCppNode(YACS::ENGINE::CppNode *cppNode, Subject *parent)
2600   : SubjectServiceNode(cppNode, parent), _cppNode(cppNode)
2601 {
2602 }
2603
2604 SubjectCppNode::~SubjectCppNode()
2605 {
2606   DEBTRACE("SubjectCppNode::~SubjectCppNode " << getName());
2607 }
2608
2609 void SubjectCppNode::clean(Command *command)
2610 {
2611   if (_askRegisterUndo)
2612     {
2613       _askRegisterUndo = false;
2614       registerUndoDestroy();
2615     }
2616   localclean(command);
2617   SubjectServiceNode::clean(command);
2618 }
2619
2620 void SubjectCppNode::localclean(Command *command)
2621 {
2622   DEBTRACE("SubjectCppNode::localClean ");
2623 }
2624
2625
2626 // ----------------------------------------------------------------------------
2627
2628 SubjectSalomeNode::SubjectSalomeNode(YACS::ENGINE::SalomeNode *salomeNode, Subject *parent)
2629   : SubjectServiceNode(salomeNode, parent), _salomeNode(salomeNode)
2630 {
2631 }
2632
2633 SubjectSalomeNode::~SubjectSalomeNode()
2634 {
2635   DEBTRACE("SubjectSalomeNode::~SubjectSalomeNode " << getName());
2636 }
2637
2638 void SubjectSalomeNode::clean(Command *command)
2639 {
2640   if (_askRegisterUndo)
2641     {
2642       _askRegisterUndo = false;
2643       registerUndoDestroy();
2644     }
2645   localclean(command);
2646   SubjectServiceNode::clean(command);
2647 }
2648
2649 void SubjectSalomeNode::localclean(Command *command)
2650 {
2651   DEBTRACE("SubjectSalomeNode::localClean ");
2652 }
2653
2654
2655 // ----------------------------------------------------------------------------
2656
2657 SubjectSalomePythonNode::SubjectSalomePythonNode(YACS::ENGINE::SalomePythonNode *salomePythonNode,
2658                                                  Subject *parent)
2659   : SubjectServiceNode(salomePythonNode, parent), _salomePythonNode(salomePythonNode)
2660 {
2661 }
2662
2663 SubjectSalomePythonNode::~SubjectSalomePythonNode()
2664 {
2665   DEBTRACE("SubjectSalomePythonNode::~SubjectSalomePythonNode " << getName());
2666 }
2667
2668 void SubjectSalomePythonNode::clean(Command *command)
2669 {
2670   if (_askRegisterUndo)
2671     {
2672       _askRegisterUndo = false;
2673       registerUndoDestroy();
2674     }
2675   localclean(command);
2676   SubjectServiceNode::clean(command);
2677 }
2678
2679 void SubjectSalomePythonNode::localclean(Command *command)
2680 {
2681   DEBTRACE("SubjectSalomePythonNode::localClean ");
2682 }
2683
2684
2685 // ----------------------------------------------------------------------------
2686
2687 SubjectXmlNode::SubjectXmlNode(YACS::ENGINE::XmlNode *xmlNode, Subject *parent)
2688   : SubjectServiceNode(xmlNode, parent), _xmlNode(xmlNode)
2689 {
2690 }
2691
2692 SubjectXmlNode::~SubjectXmlNode()
2693 {
2694   DEBTRACE("SubjectXmlNode::~SubjectXmlNode " << getName());
2695 }
2696
2697 void SubjectXmlNode::clean(Command *command)
2698 {
2699   if (_askRegisterUndo)
2700     {
2701       _askRegisterUndo = false;
2702       registerUndoDestroy();
2703     }
2704   localclean(command);
2705   SubjectServiceNode::clean(command);
2706 }
2707
2708 void SubjectXmlNode::localclean(Command *command)
2709 {
2710   DEBTRACE("SubjectXmlNode::localClean ");
2711 }
2712
2713
2714 // ----------------------------------------------------------------------------
2715
2716 SubjectSplitterNode::SubjectSplitterNode(YACS::ENGINE::SplitterNode *splitterNode, Subject *parent)
2717   : SubjectElementaryNode(splitterNode, parent), _splitterNode(splitterNode)
2718 {
2719   _destructible = false;
2720 }
2721
2722 SubjectSplitterNode::~SubjectSplitterNode()
2723 {
2724   DEBTRACE("SubjectSplitterNode::~SubjectSplitterNode " << getName());
2725 }
2726
2727 void SubjectSplitterNode::clean(Command *command)
2728 {
2729   if (_askRegisterUndo)
2730     {
2731       _askRegisterUndo = false;
2732       registerUndoDestroy();
2733     }
2734   localclean(command);
2735   SubjectElementaryNode::clean(command);
2736 }
2737
2738 void SubjectSplitterNode::localclean(Command *command)
2739 {
2740   DEBTRACE("SubjectSplitterNode::localClean ");
2741 }
2742
2743
2744 std::string SubjectSplitterNode::getName()
2745 {
2746   return "splitter";
2747 }
2748
2749 // ----------------------------------------------------------------------------
2750
2751 SubjectDataNode::SubjectDataNode(YACS::ENGINE::DataNode *dataNode, Subject *parent)
2752   : SubjectElementaryNode(dataNode, parent), _dataNode(dataNode)
2753 {
2754   _destructible = true;
2755 }
2756
2757 SubjectDataNode::~SubjectDataNode()
2758 {
2759   DEBTRACE("SubjectDataNode::~SubjectDataNode " << getName());
2760 }
2761
2762 void SubjectDataNode::clean(Command *command)
2763 {
2764   if (_askRegisterUndo)
2765     {
2766       _askRegisterUndo = false;
2767       registerUndoDestroy();
2768     }
2769   localclean(command);
2770   SubjectElementaryNode::clean(command);
2771 }
2772
2773 void SubjectDataNode::localclean(Command *command)
2774 {
2775   DEBTRACE("SubjectDataNode::localClean ");
2776 }
2777
2778 // ----------------------------------------------------------------------------
2779
2780 SubjectPresetNode::SubjectPresetNode(YACS::ENGINE::PresetNode *presetNode, Subject *parent)
2781   : SubjectDataNode(presetNode, parent), _presetNode(presetNode)
2782 {
2783   _destructible = true;
2784 }
2785
2786 SubjectPresetNode::~SubjectPresetNode()
2787 {
2788   DEBTRACE("SubjectPresetNode::~SubjectPresetNode " << getName());
2789 }
2790
2791 void SubjectPresetNode::clean(Command *command)
2792 {
2793   if (_askRegisterUndo)
2794     {
2795       _askRegisterUndo = false;
2796       registerUndoDestroy();
2797     }
2798   localclean(command);
2799   SubjectDataNode::clean(command);
2800 }
2801
2802 void SubjectPresetNode::localclean(Command *command)
2803 {
2804   DEBTRACE("SubjectPresetNode::localClean ");
2805 }
2806
2807 // ----------------------------------------------------------------------------
2808
2809 SubjectOutNode::SubjectOutNode(YACS::ENGINE::OutNode *outNode, Subject *parent)
2810   : SubjectDataNode(outNode, parent), _outNode(outNode)
2811 {
2812   _destructible = true;
2813 }
2814
2815 SubjectOutNode::~SubjectOutNode()
2816 {
2817   DEBTRACE("SubjectOutNode::~SubjectOutNode " << getName());
2818 }
2819
2820 void SubjectOutNode::clean(Command *command)
2821 {
2822   if (_askRegisterUndo)
2823     {
2824       _askRegisterUndo = false;
2825       registerUndoDestroy();
2826     }
2827   localclean(command);
2828   SubjectDataNode::clean(command);
2829 }
2830
2831 void SubjectOutNode::localclean(Command *command)
2832 {
2833   DEBTRACE("SubjectOutNode::localClean ");
2834 }
2835
2836 // ----------------------------------------------------------------------------
2837
2838 SubjectStudyInNode::SubjectStudyInNode(YACS::ENGINE::StudyInNode *studyInNode, Subject *parent)
2839   : SubjectDataNode(studyInNode, parent), _studyInNode(studyInNode)
2840 {
2841   _destructible = true;
2842 }
2843
2844 SubjectStudyInNode::~SubjectStudyInNode()
2845 {
2846   DEBTRACE("SubjectStudyInNode::~SubjectStudyInNode " << getName());
2847 }
2848
2849 void SubjectStudyInNode::clean(Command *command)
2850 {
2851   if (_askRegisterUndo)
2852     {
2853       _askRegisterUndo = false;
2854       registerUndoDestroy();
2855     }
2856   localclean(command);
2857   SubjectDataNode::clean(command);
2858 }
2859
2860 void SubjectStudyInNode::localclean(Command *command)
2861 {
2862   DEBTRACE("SubjectStudyInNode::localClean ");
2863 }
2864
2865 // ----------------------------------------------------------------------------
2866
2867 SubjectStudyOutNode::SubjectStudyOutNode(YACS::ENGINE::StudyOutNode *studyOutNode, Subject *parent)
2868   : SubjectDataNode(studyOutNode, parent), _studyOutNode(studyOutNode)
2869 {
2870   _destructible = true;
2871 }
2872
2873 SubjectStudyOutNode::~SubjectStudyOutNode()
2874 {
2875   DEBTRACE("SubjectStudyOutNode::~SubjectStudyOutNode " << getName());
2876 }
2877
2878 void SubjectStudyOutNode::clean(Command *command)
2879 {
2880   if (_askRegisterUndo)
2881     {
2882       _askRegisterUndo = false;
2883       registerUndoDestroy();
2884     }
2885   localclean(command);
2886   SubjectDataNode::clean(command);
2887 }
2888
2889 void SubjectStudyOutNode::localclean(Command *command)
2890 {
2891   DEBTRACE("SubjectStudyOutNode::localClean ");
2892 }
2893
2894 // ----------------------------------------------------------------------------
2895
2896 SubjectForLoop::SubjectForLoop(YACS::ENGINE::ForLoop *forLoop, Subject *parent)
2897   : SubjectComposedNode(forLoop, parent), _forLoop(forLoop)
2898 {
2899   _body = 0;
2900 }
2901
2902 SubjectForLoop::~SubjectForLoop()
2903 {
2904   DEBTRACE("SubjectForLoop::~SubjectForLoop " << getName());
2905 }
2906
2907 void SubjectForLoop::clean(Command *command)
2908 {
2909   if (_askRegisterUndo)
2910     {
2911       _askRegisterUndo = false;
2912       registerUndoDestroy();
2913     }
2914   localclean(command);
2915   SubjectComposedNode::clean(command);
2916 }
2917
2918 void SubjectForLoop::localclean(Command *command)
2919 {
2920   DEBTRACE("SubjectForLoop::localClean ");
2921   if (_body)
2922     erase(_body);
2923 }
2924
2925 void SubjectForLoop::recursiveUpdate(GuiEvent event, int type, Subject* son)
2926 {
2927   update(event, type, son);
2928   if (_body)
2929     _body->recursiveUpdate(event, type, son);
2930 }
2931
2932 SubjectNode* SubjectForLoop::addNode(YACS::ENGINE::Catalog *catalog,
2933                                      std::string compo,
2934                                      std::string type,
2935                                      std::string name,
2936                                      bool newCompoInst)
2937 {
2938   DEBTRACE("SubjectForLoop::addNode("<<catalog<<","<<compo<<","<<type<<","<<name<<")");
2939   SubjectNode* body = 0;
2940   if (_body)
2941     {
2942       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a loop, put the nodes in a bloc"; 
2943       return body;
2944     }
2945   body = createNode(catalog, compo, type, name, newCompoInst);
2946   return body;
2947 }
2948
2949 void SubjectForLoop::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
2950 {
2951   if (isCut)
2952     _body = 0;
2953   else
2954     _body = son;
2955 }
2956
2957 void SubjectForLoop::completeChildrenSubjectList(SubjectNode *son)
2958 {
2959   _body = son;
2960 }
2961
2962 bool SubjectForLoop::setNbSteps(std::string nbSteps)
2963 {
2964   DEBTRACE("SubjectForLoop::setNbSteps " << nbSteps);
2965   Proc *proc = GuiContext::getCurrent()->getProc();
2966   CommandSetForLoopSteps *command =
2967     new CommandSetForLoopSteps(proc->getChildName(getNode()), nbSteps);
2968   if (command->execute())
2969     {
2970       GuiContext::getCurrent()->getInvoc()->add(command);
2971       return true;
2972     }
2973   else delete command;
2974   return false;
2975 }
2976 bool SubjectForLoop::hasValue()
2977 {
2978   return true;
2979 }
2980
2981 std::string SubjectForLoop::getValue()
2982 {
2983   return _forLoop->edGetNbOfTimesInputPort()->getAsString();
2984 }
2985
2986 // ----------------------------------------------------------------------------
2987
2988 SubjectWhileLoop::SubjectWhileLoop(YACS::ENGINE::WhileLoop *whileLoop, Subject *parent)
2989   : SubjectComposedNode(whileLoop, parent), _whileLoop(whileLoop)
2990 {
2991   _body = 0;
2992 }
2993
2994 SubjectWhileLoop::~SubjectWhileLoop()
2995 {
2996   DEBTRACE("SubjectWhileLoop::~SubjectWhileLoop " << getName());
2997 }
2998
2999 void SubjectWhileLoop::clean(Command *command)
3000 {
3001   if (_askRegisterUndo)
3002     {
3003       _askRegisterUndo = false;
3004       registerUndoDestroy();
3005     }
3006   localclean(command);
3007   SubjectComposedNode::clean(command);
3008 }
3009
3010 void SubjectWhileLoop::localclean(Command *command)
3011 {
3012   DEBTRACE("SubjectWhileLoop::localClean ");
3013   if (_body)
3014     erase(_body);
3015 }
3016
3017 void SubjectWhileLoop::recursiveUpdate(GuiEvent event, int type, Subject* son)
3018 {
3019   update(event, type, son);
3020   if (_body)
3021     _body->recursiveUpdate(event, type, son);
3022 }
3023
3024 SubjectNode* SubjectWhileLoop::addNode(YACS::ENGINE::Catalog *catalog,
3025                                        std::string compo,
3026                                        std::string type,
3027                                        std::string name,
3028                                        bool newCompoInst)
3029 {
3030   DEBTRACE("SubjectWhileLoop::addNode(catalog, compo, type, name)");
3031   SubjectNode* body = 0;
3032   if (_body)
3033     {
3034       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a loop, put the nodes in a bloc"; 
3035       return body;
3036     }
3037   body = createNode(catalog, compo, type, name, newCompoInst);
3038   return body;
3039 }
3040
3041 void SubjectWhileLoop::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
3042 {
3043   if (isCut)
3044     _body = 0;
3045   else
3046     _body = son;
3047 }
3048
3049 void SubjectWhileLoop::completeChildrenSubjectList(SubjectNode *son)
3050 {
3051   _body = son;
3052 }
3053
3054 bool SubjectWhileLoop::setCondition(std::string condition)
3055 {
3056   DEBTRACE("SubjectWhileLoop::setCondition " << condition);
3057   Proc *proc = GuiContext::getCurrent()->getProc();
3058   CommandSetWhileCondition *command =
3059     new CommandSetWhileCondition(proc->getChildName(getNode()), condition);
3060   if (command->execute())
3061     {
3062       GuiContext::getCurrent()->getInvoc()->add(command);
3063       return true;
3064     }
3065   else delete command;
3066   return false;
3067 }
3068
3069 bool SubjectWhileLoop::hasValue()
3070 {
3071   return true;
3072 }
3073
3074 std::string SubjectWhileLoop::getValue()
3075 {
3076   return _whileLoop->edGetConditionPort()->getAsString();
3077 }
3078
3079 // ----------------------------------------------------------------------------
3080
3081 SubjectSwitch::SubjectSwitch(YACS::ENGINE::Switch *aSwitch, Subject *parent)
3082   : SubjectComposedNode(aSwitch, parent), _switch(aSwitch)
3083 {
3084   _bodyMap.clear();
3085 }
3086
3087 SubjectSwitch::~SubjectSwitch()
3088 {
3089   DEBTRACE("SubjectSwitch::~SubjectSwitch " << getName());
3090 }
3091
3092 void SubjectSwitch::clean(Command *command)
3093 {
3094   if (_askRegisterUndo)
3095     {
3096       _askRegisterUndo = false;
3097       registerUndoDestroy();
3098     }
3099   localclean(command);
3100   SubjectComposedNode::clean(command);
3101 }
3102
3103 void SubjectSwitch::localclean(Command *command)
3104 {
3105   DEBTRACE("SubjectSwitch::localClean ");
3106   map<int, SubjectNode*>::iterator it;
3107   map<int, SubjectNode*> bodyMapCpy = _bodyMap;
3108   for (it = bodyMapCpy.begin(); it != bodyMapCpy.end(); ++it)
3109     erase((*it).second);
3110 }
3111
3112 void SubjectSwitch::recursiveUpdate(GuiEvent event, int type, Subject* son)
3113 {
3114   update(event, type, son);
3115   map<int, SubjectNode*>::iterator it = _bodyMap.begin();
3116   for (; it != _bodyMap.end(); ++it)
3117     (*it).second->recursiveUpdate(event, type, son);
3118 }
3119
3120 SubjectNode* SubjectSwitch::addNode(YACS::ENGINE::Catalog *catalog,
3121                                     std::string compo,
3122                                     std::string type,
3123                                     std::string name,
3124                                     bool newCompoInst,
3125                                     int swCase,
3126                                     bool replace)
3127 {
3128   DEBTRACE("SubjectSwitch::addNode("<<catalog<<","<<compo<<","<<type<<","<<name<<","<<swCase<<","<<(int)replace<<")");
3129   SubjectNode* body = 0;
3130   if (!replace && _bodyMap.count(swCase))
3131     {
3132       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a switch case, put the nodes in a bloc"; 
3133       return body;
3134     }
3135   body = createNode(catalog, compo, type, name, newCompoInst, swCase);
3136   return body;
3137 }
3138
3139 void SubjectSwitch::removeNode(SubjectNode* son)
3140 {
3141   DEBTRACE("SubjectSwitch::removeNode("<<son->getName()<<")");
3142   if (son)
3143   {
3144     int id;
3145     bool isFound = false;
3146     map<int, SubjectNode*>::const_iterator it;
3147     for (it = _bodyMap.begin(); it != _bodyMap.end(); ++it)
3148     {
3149       if ( (*it).second == son )
3150       {
3151         isFound = true;
3152         id = (*it).first;
3153         break;
3154       }
3155     }
3156     if (isFound)
3157     {
3158       DEBTRACE("id = "<<id);
3159       _bodyMap.erase(id);
3160     }
3161   }
3162 }
3163
3164 std::map<int, SubjectNode*> SubjectSwitch::getBodyMap()
3165 {
3166   return _bodyMap;
3167 }
3168
3169 void SubjectSwitch::houseKeepingAfterCutPaste(bool isCut, SubjectNode *son)
3170 {
3171   DEBTRACE("SubjectSwitch::houseKeepingAfterCutPaste");
3172   if (isCut)
3173     _bodyMap.erase(_switch->getRankOfNode(son->getNode()));
3174   else
3175     _bodyMap[_switch->getRankOfNode(son->getNode())] = son;
3176 }
3177
3178
3179 void SubjectSwitch::completeChildrenSubjectList(SubjectNode *son)
3180 {
3181   DEBTRACE("SubjectSwitch::completeChildrenSubjectList");
3182   _bodyMap[_switch->getRankOfNode(son->getNode())] = son;
3183 }
3184
3185 SubjectNode* SubjectSwitch::getChild(YACS::ENGINE::Node* node) const
3186 {
3187   SubjectNode* aChild = 0;
3188
3189   if (node)
3190   {
3191     map<int, SubjectNode*>::const_iterator it;
3192     for (it = _bodyMap.begin(); it != _bodyMap.end(); ++it)
3193       if ( (*it).second->getNode() == node )
3194       {
3195         aChild = (*it).second;
3196         break;
3197       }
3198   }
3199
3200   return aChild;
3201 }
3202
3203 bool SubjectSwitch::setSelect(std::string select)
3204 {
3205   DEBTRACE("SubjectSwitch::setSelect " << select);
3206   Proc *proc = GuiContext::getCurrent()->getProc();
3207   CommandSetSwitchSelect *command =
3208     new CommandSetSwitchSelect(proc->getChildName(getNode()), select);
3209   if (command->execute())
3210     {
3211       GuiContext::getCurrent()->getInvoc()->add(command);
3212       return true;
3213     }
3214   else delete command;
3215   return false;
3216 }
3217
3218 bool SubjectSwitch::setCase(std::string caseId, SubjectNode* snode)
3219 {
3220   DEBTRACE("SubjectSwitch::setCase " << caseId);
3221   Proc *proc = GuiContext::getCurrent()->getProc();
3222
3223   Switch* aSwitch = dynamic_cast<Switch*>(getNode());
3224   Node* node =snode->getNode();
3225   int previousRank = aSwitch->getRankOfNode(node);
3226   int newRank = atoi(caseId.c_str());
3227   if (previousRank == newRank) return true; // nothing to do.
3228
3229   CommandSetSwitchCase *command =
3230     new CommandSetSwitchCase(proc->getChildName(getNode()),
3231                              proc->getChildName(snode->getNode()),
3232                              caseId);
3233   if (command->execute())
3234     {
3235       GuiContext::getCurrent()->getInvoc()->add(command);
3236       return true;
3237     }
3238   else delete command;
3239   return false;
3240 }
3241
3242 bool SubjectSwitch::hasValue()
3243 {
3244   return true;
3245 }
3246
3247 std::string SubjectSwitch::getValue()
3248 {
3249   return _switch->edGetConditionPort()->getAsString();
3250 }
3251
3252 // ----------------------------------------------------------------------------
3253
3254 SubjectDynParaLoop::SubjectDynParaLoop(YACS::ENGINE::DynParaLoop * dynParaLoop, Subject * parent)
3255   : SubjectComposedNode(dynParaLoop, parent), _dynParaLoop(dynParaLoop)
3256 {
3257   _subjectExecNode = NULL;
3258   _subjectInitNode = NULL;
3259   _subjectFinalizeNode = NULL;
3260 }
3261
3262 SubjectDynParaLoop::~SubjectDynParaLoop()
3263 {
3264   DEBTRACE("SubjectDynParaLoop::~SubjectDynParaLoop " << getName());
3265 }
3266
3267 void SubjectDynParaLoop::recursiveUpdate(GuiEvent event, int type, Subject * son)
3268 {
3269   update(event, type, son);
3270   if (_subjectExecNode)
3271     _subjectExecNode->recursiveUpdate(event, type, son);
3272   if (_subjectInitNode)
3273     _subjectInitNode->recursiveUpdate(event, type, son);
3274   if (_subjectFinalizeNode)
3275     _subjectFinalizeNode->recursiveUpdate(event, type, son);
3276 }
3277
3278 SubjectNode * SubjectDynParaLoop::addNode(YACS::ENGINE::Catalog * catalog,
3279                                           std::string compo,
3280                                           std::string type,
3281                                           std::string name,
3282                                           bool newCompoInst)
3283 {
3284   DEBTRACE("SubjectDynParaLoop::addNode(catalog, compo, type, name)");
3285   if (_subjectExecNode)
3286     {
3287       GuiContext::getCurrent()->_lastErrorMessage = "If you need several nodes in a loop, "
3288                                                     "put the nodes in a bloc";
3289       return NULL;
3290     }
3291   return createNode(catalog, compo, type, name, newCompoInst);
3292 }
3293
3294 void SubjectDynParaLoop::houseKeepingAfterCutPaste(bool isCut, SubjectNode * son)
3295 {
3296   if (isCut)
3297     removeNode(son);
3298   else
3299     _subjectExecNode = son;
3300 }
3301
3302 void SubjectDynParaLoop::clean(Command * command)
3303 {
3304   if (_askRegisterUndo)
3305     {
3306       _askRegisterUndo = false;
3307       registerUndoDestroy();
3308     }
3309   localclean(command);
3310   SubjectComposedNode::clean(command);
3311 }
3312
3313 void SubjectDynParaLoop::localclean(Command * command)
3314 {
3315   DEBTRACE("SubjectDynParaLoop::localClean ");
3316   if (_subjectExecNode)
3317     {
3318       DEBTRACE(_subjectExecNode->getName());
3319       erase(_subjectExecNode);
3320     }
3321   if (_subjectInitNode)
3322     {
3323       DEBTRACE(_subjectInitNode->getName());
3324       erase(_subjectInitNode);
3325     }
3326   if (_subjectFinalizeNode)
3327     {
3328       DEBTRACE(_subjectFinalizeNode->getName());
3329       erase(_subjectFinalizeNode);
3330     }
3331 }
3332
3333 void SubjectDynParaLoop::completeChildrenSubjectList(SubjectNode * son)
3334 {
3335   YASSERT(son);
3336   if (son->getNode() == _dynParaLoop->getExecNode())
3337     _subjectExecNode = son;
3338   else if (son->getNode() == _dynParaLoop->getInitNode())
3339     _subjectInitNode = son;
3340   else if (son->getNode() == _dynParaLoop->getFinalizeNode())
3341     _subjectFinalizeNode = son;
3342   else
3343     YASSERT(false);
3344 }
3345
3346 void SubjectDynParaLoop::removeNode(SubjectNode * child)
3347 {
3348   YASSERT(child);
3349   if (child == _subjectExecNode)
3350     _subjectExecNode = NULL;
3351   else if (child == _subjectInitNode)
3352     _subjectInitNode = NULL;
3353   else if (child == _subjectFinalizeNode)
3354     _subjectFinalizeNode = NULL;
3355   else
3356     YASSERT(false);
3357 }
3358
3359 SubjectNode * SubjectDynParaLoop::getChild(YACS::ENGINE::Node * node) const
3360 {
3361   return _subjectExecNode;
3362 }
3363
3364 bool SubjectDynParaLoop::setNbBranches(std::string nbBranches)
3365 {
3366   DEBTRACE("SubjectDynParaLoop::setNbBranches " << nbBranches);
3367   Proc * proc = GuiContext::getCurrent()->getProc();
3368   CommandSetForEachBranch * command =
3369     new CommandSetForEachBranch(proc->getChildName(getNode()), nbBranches);
3370   if (command->execute())
3371     {
3372       GuiContext::getCurrent()->getInvoc()->add(command);
3373       return true;
3374     }
3375   else delete command;
3376   return false;
3377 }
3378
3379 bool SubjectDynParaLoop::hasValue()
3380 {
3381   return true;
3382 }
3383
3384 std::string SubjectDynParaLoop::getValue()
3385 {
3386   return _dynParaLoop->edGetNbOfBranchesPort()->getAsString();
3387 }
3388
3389 // ----------------------------------------------------------------------------
3390
3391 SubjectForEachLoop::SubjectForEachLoop(YACS::ENGINE::ForEachLoop *forEachLoop, Subject *parent)
3392   : SubjectDynParaLoop(forEachLoop, parent), _forEachLoop(forEachLoop)
3393 {
3394   _splitter = 0;
3395 }
3396
3397 SubjectForEachLoop::~SubjectForEachLoop()
3398 {
3399   DEBTRACE("SubjectForEachLoop::~SubjectForEachLoop " << getName());
3400 }
3401
3402 void SubjectForEachLoop::clean(Command *command)
3403 {
3404   if (_askRegisterUndo)
3405     {
3406       _askRegisterUndo = false;
3407       registerUndoDestroy();
3408     }
3409   Node* aSplitterEngine = 0;
3410   if (_splitter) aSplitterEngine = _splitter->getNode();
3411
3412   localclean(command);
3413   SubjectDynParaLoop::clean(command);
3414
3415   if (_forEachLoop && aSplitterEngine)
3416     {
3417       DEBTRACE("SubjectForEachLoop::clean: remove for each loop splitter");
3418       _forEachLoop->edRemoveChild(aSplitterEngine);
3419     }
3420 }
3421
3422 void SubjectForEachLoop::localclean(Command *command)
3423 {
3424   DEBTRACE("SubjectForEachLoop::localClean ");
3425   if (_splitter)
3426     {
3427       DEBTRACE(_splitter->getName());
3428       erase(_splitter);
3429     }
3430 }
3431
3432 void SubjectForEachLoop::completeChildrenSubjectList(SubjectNode *son)
3433 {
3434   if (son && son->getName() == ForEachLoop::NAME_OF_SPLITTERNODE)
3435     _splitter = son;
3436   else
3437     SubjectDynParaLoop::completeChildrenSubjectList(son);
3438 }
3439
3440 void SubjectForEachLoop::removeNode(SubjectNode * child)
3441 {
3442   YASSERT(child);
3443   if (child->getName() == ForEachLoop::NAME_OF_SPLITTERNODE)
3444     _splitter = NULL;
3445   else {
3446     SubjectDynParaLoop::removeNode(child);
3447   }
3448 }
3449
3450 // ----------------------------------------------------------------------------
3451
3452 SubjectOptimizerLoop::SubjectOptimizerLoop(YACS::ENGINE::OptimizerLoop *optimizerLoop,
3453                                            Subject *parent)
3454   : SubjectDynParaLoop(optimizerLoop, parent), _optimizerLoop(optimizerLoop)
3455 {
3456 }
3457
3458 SubjectOptimizerLoop::~SubjectOptimizerLoop()
3459 {
3460   DEBTRACE("SubjectOptimizerLoop::~SubjectOptimizerLoop " << getName());
3461 }
3462
3463 void SubjectOptimizerLoop::clean(Command *command)
3464 {
3465   if (_askRegisterUndo)
3466     {
3467       _askRegisterUndo = false;
3468       registerUndoDestroy();
3469     }
3470   localclean(command);
3471   SubjectDynParaLoop::clean(command);
3472 }
3473
3474 void SubjectOptimizerLoop::localclean(Command *command)
3475 {
3476   DEBTRACE("SubjectOptimizerLoop::localClean ");
3477 }
3478
3479 bool SubjectOptimizerLoop::setAlgorithm(const std::string& alglib,const std::string& symbol)
3480 {
3481   DEBTRACE("SubjectOptimizerLoop::setAlgorithm " << alglib << " " << symbol);
3482   Proc *proc = GuiContext::getCurrent()->getProc();
3483   CommandSetAlgo *command = new CommandSetAlgo(proc->getChildName(getNode()), alglib, symbol);
3484   if (command->execute())
3485     {
3486       GuiContext::getCurrent()->getInvoc()->add(command);
3487       return true;
3488     }
3489   else delete command;
3490   return false;
3491 }
3492
3493 // ----------------------------------------------------------------------------
3494
3495 SubjectDataPort::SubjectDataPort(YACS::ENGINE::DataPort* port, Subject *parent)
3496   : Subject(parent), _dataPort(port)
3497 {
3498   _listSubjectLink.clear();
3499   _execValue = "";
3500 }
3501
3502 SubjectDataPort::~SubjectDataPort()
3503 {
3504   DEBTRACE("SubjectDataPort::~SubjectDataPort " << getName());
3505   if (isDestructible())
3506     {
3507       Node* node = _dataPort->getNode();
3508       YASSERT(node);
3509       ElementaryNode * father = dynamic_cast<ElementaryNode*>(node);
3510       if (father)
3511         {
3512           DEBTRACE("father->edRemovePort(_dataPort)");
3513           try
3514             {
3515               father->edRemovePort(_dataPort);
3516             }
3517           catch (YACS::Exception &e)
3518             {
3519               DEBTRACE("------------------------------------------------------------------------------");
3520               DEBTRACE("SubjectDataPort::~SubjectDataPort: father->edRemovePort: YACS exception " << e.what());
3521               DEBTRACE("------------------------------------------------------------------------------");
3522             }
3523         }
3524     }
3525 }
3526
3527 void SubjectDataPort::clean(Command *command)
3528 {
3529   if (_askRegisterUndo)
3530     {
3531       _askRegisterUndo = false;
3532       registerUndoDestroy();
3533     }
3534   localclean(command);
3535   Subject::clean(command);
3536 }
3537
3538 void SubjectDataPort::localclean(Command *command)
3539 {
3540   DEBTRACE("SubjectDataPort::localClean ");
3541   list<SubjectLink*> lsl = getListOfSubjectLink();
3542   for (list<SubjectLink*>::iterator it = lsl.begin(); it != lsl.end(); ++it)
3543     erase(*it);
3544 }
3545
3546 std::string SubjectDataPort::getName()
3547 {
3548   return _dataPort->getName();
3549 }
3550
3551 bool SubjectDataPort::setName(std::string name)
3552 {
3553   DEBTRACE("SubjectDataPort::setName " << name);
3554   Proc *proc = GuiContext::getCurrent()->getProc();
3555   string position = "";
3556   Node *node = getPort()->getNode();
3557   if (proc != dynamic_cast<Proc*>(node))
3558     position = proc->getChildName(node);
3559   else
3560     position = node->getName();
3561
3562   Command *command = 0;
3563   bool isIn = dynamic_cast<InPort*>(_dataPort);
3564   if (isIn) 
3565     command = new CommandRenameInDataPort(position, _dataPort->getName(),name, getType());
3566   else 
3567     command = new CommandRenameOutDataPort(position, _dataPort->getName(),name, getType());
3568
3569   if (command->execute())
3570     {
3571       GuiContext::getCurrent()->getInvoc()->add(command);
3572       return true;
3573     }
3574   else delete command;
3575   return false;
3576 }
3577
3578 YACS::ENGINE::DataPort* SubjectDataPort::getPort()
3579 {
3580   return _dataPort;
3581 }
3582
3583 bool SubjectDataPort::tryCreateLink(SubjectDataPort *subOutport, SubjectDataPort *subInport,bool control)
3584 {
3585   DEBTRACE("SubjectDataPort::tryCreateLink");
3586
3587   InPort *inp = dynamic_cast<InPort*>(subInport->getPort());
3588   OutPort *outp = dynamic_cast<OutPort*>(subOutport->getPort());
3589   if (outp && outp->isAlreadyLinkedWith(inp))
3590     {
3591       DEBTRACE("isAlreadyLinkedWith");
3592       GuiContext::getCurrent()->_lastErrorMessage = "Ports are already linked"; 
3593       return false;
3594     }
3595
3596   Proc *proc = GuiContext::getCurrent()->getProc();
3597
3598   string outNodePos = "";
3599   SubjectNode *sno = dynamic_cast<SubjectNode*>(subOutport->getParent());
3600   YASSERT(sno);
3601   Node *outNode = sno->getNode();
3602   outNodePos = proc->getChildName(outNode);
3603   string outportName = subOutport->getName();
3604
3605   string inNodePos = "";
3606   SubjectNode *sni = dynamic_cast<SubjectNode*>(subInport->getParent());
3607   YASSERT(sni);
3608   Node *inNode = sni->getNode();
3609   inNodePos = proc->getChildName(inNode);
3610   string inportName = subInport->getName();
3611
3612   CommandAddLink *command = new CommandAddLink(outNodePos, outportName, subOutport->getType(),
3613                                                inNodePos, inportName, subInport->getType(), control);
3614   if (command->execute())
3615     {
3616       GuiContext::getCurrent()->getInvoc()->add(command);
3617       return true;
3618     }
3619   else
3620     {
3621       delete command;
3622       return false;
3623     }
3624 }
3625
3626 /*! Generic method do nothing.
3627  *  Implementation in SubjectInputPort and SubjectOutputPort.
3628  */
3629 bool SubjectDataPort::setValue(std::string value)
3630 {
3631   return false;
3632 }
3633
3634 void SubjectDataPort::setExecValue(std::string value)
3635 {
3636   _execValue = value;
3637 }
3638
3639 std::string SubjectDataPort::getExecValue()
3640 {
3641   return _execValue;
3642 }
3643
3644 void SubjectDataPort::registerUndoDestroy()
3645 {
3646   DEBTRACE("SubjectDataPort::registerUndoDestroy");
3647   Proc *proc = GuiContext::getCurrent()->getProc();
3648   SubjectNode *sno = dynamic_cast<SubjectNode*>(getParent());
3649   YASSERT(sno);
3650   Node *node = sno->getNode();
3651   string nodeName = proc->getChildName(node);
3652   string portName = getName();
3653   ElementaryNode* father = dynamic_cast<ElementaryNode*>(node);
3654   YASSERT(father);
3655
3656   DataPort *port = getPort();
3657   TypeCode *dtyp = port->edGetType();
3658   string typeName = dtyp->name();
3659   Catalog *undoCata = GuiContext::getCurrent()->getInvoc()->getUndoCata();
3660   undoCata->_typeMap[typeName] = dtyp;
3661
3662   Command *command = 0;
3663   Command *comm2 =0;
3664   TypeOfElem elemType = getType();
3665   switch (elemType)
3666     {
3667     case INPUTPORT:
3668       command = new CommandAddInputPortFromCatalog(undoCata, typeName, nodeName, portName);
3669       {
3670         int rang = 1;
3671         int nbUp = 0;
3672         list<InputPort*> plist = father->getSetOfInputPort();
3673         list<InputPort*>::iterator pos = plist.begin();
3674         for (; (*pos) != port; pos++)
3675           rang++;
3676         nbUp = plist.size() -rang;
3677         if (nbUp)
3678           comm2 = new CommandOrderInputPorts(nodeName, portName, nbUp);
3679       }
3680       break;
3681     case OUTPUTPORT:
3682       command = new CommandAddOutputPortFromCatalog(undoCata, typeName, nodeName, portName);
3683       {
3684         int rang = 1;
3685         int nbUp = 0;
3686         list<OutputPort*> plist = father->getSetOfOutputPort();
3687         list<OutputPort*>::iterator pos = plist.begin();
3688         for (; (*pos) != port; pos++)
3689           rang++;
3690         nbUp = plist.size() -rang;
3691         if (nbUp)
3692           comm2 = new CommandOrderOutputPorts(nodeName, portName, nbUp);
3693       }
3694       break;
3695     case INPUTDATASTREAMPORT:
3696       command = new CommandAddIDSPortFromCatalog(undoCata, typeName, nodeName, portName);
3697       break;
3698     case OUTPUTDATASTREAMPORT:
3699       command = new CommandAddODSPortFromCatalog(undoCata, typeName, nodeName, portName);
3700       break;
3701     }
3702   if (command)
3703     GuiContext::getCurrent()->getInvoc()->add(command);
3704   if (comm2)
3705     GuiContext::getCurrent()->getInvoc()->add(comm2);
3706   //save links
3707   list<SubjectLink*> lsl = getListOfSubjectLink();
3708   for (list<SubjectLink*>::iterator it = lsl.begin(); it != lsl.end(); ++it)
3709     {
3710       (*it)->registerUndoDestroy();
3711     }
3712 }
3713
3714
3715 // ----------------------------------------------------------------------------
3716
3717 SubjectInputPort::SubjectInputPort(YACS::ENGINE::InputPort *port, Subject *parent)
3718   : SubjectDataPort(port, parent), _inputPort(port)
3719 {
3720   Node *node = _inputPort->getNode();
3721   if (ForLoop* forloop = dynamic_cast<ForLoop*>(node))
3722     {
3723       if (_inputPort->getName() == "nsteps") _destructible = false;
3724     }
3725   else if (WhileLoop* whileloop = dynamic_cast<WhileLoop*>(node))
3726     {
3727       if (_inputPort->getName() == "condition") _destructible = false;
3728     }
3729   else if (Switch* aSwitch = dynamic_cast<Switch*>(node))
3730     {
3731       if (_inputPort->getName() == "select") _destructible = false;
3732     }
3733   else if (ForEachLoop* foreach = dynamic_cast<ForEachLoop*>(node))
3734     {
3735       if (_inputPort->getName() == "nbBranches") _destructible = false;
3736     }
3737   else if (OptimizerLoop* optil = dynamic_cast<OptimizerLoop*>(node))
3738     {
3739       if (_inputPort->getName() == "nbBranches") _destructible = false;
3740     }
3741   else if (SplitterNode* split = dynamic_cast<SplitterNode*>(node))
3742     {
3743       if (_inputPort->getName() == "SmplsCollection") _destructible = false;
3744     }
3745
3746 }
3747
3748 SubjectInputPort::~SubjectInputPort()
3749 {
3750   DEBTRACE("SubjectInputPort::~SubjectInputPort " << getName());
3751 }
3752
3753 void SubjectInputPort::clean(Command *command)
3754 {
3755   if (_askRegisterUndo)
3756     {
3757       _askRegisterUndo = false;
3758       registerUndoDestroy();
3759     }
3760   localclean(command);
3761   SubjectDataPort::clean(command);
3762 }
3763
3764 void SubjectInputPort::localclean(Command *command)
3765 {
3766   DEBTRACE("SubjectInputPort::localClean ");
3767   if (_parent)
3768     {
3769       SubjectElementaryNode* elem = dynamic_cast<SubjectElementaryNode*>(_parent);
3770       if (elem) elem->removePort(this);
3771     }
3772 }
3773
3774 bool SubjectInputPort::setValue(std::string value)
3775 {
3776   DEBTRACE("SubjectInputPort::setValue " << value);
3777   Proc *proc = GuiContext::getCurrent()->getProc();
3778   CommandSetInPortValue *command =
3779     new CommandSetInPortValue(proc->getChildName(getPort()->getNode()), getName(), value);
3780   if (command->execute())
3781     {
3782       GuiContext::getCurrent()->getInvoc()->add(command);
3783       return true;
3784     }
3785   else delete command;
3786   return false;
3787 }
3788
3789 // ----------------------------------------------------------------------------
3790
3791 SubjectOutputPort::SubjectOutputPort(YACS::ENGINE::OutputPort *port, Subject *parent)
3792   : SubjectDataPort(port, parent), _outputPort(port)
3793 {
3794   if (DynParaLoop* dynloop = dynamic_cast<DynParaLoop*>(_outputPort->getNode()))
3795     {
3796       if (_outputPort == dynloop->edGetSamplePort()) _destructible = false;
3797     }
3798 }
3799
3800 SubjectOutputPort::~SubjectOutputPort()
3801 {
3802   DEBTRACE("SubjectOutputPort::~SubjectOutputPort " << getName());
3803 }
3804
3805 void SubjectOutputPort::clean(Command *command)
3806 {
3807   if (_askRegisterUndo)
3808     {
3809       _askRegisterUndo = false;
3810       registerUndoDestroy();
3811     }
3812   localclean(command);
3813   SubjectDataPort::clean(command);
3814 }
3815
3816 void SubjectOutputPort::localclean(Command *command)
3817 {
3818   DEBTRACE("SubjectOutputPort::localClean ");
3819   if (_parent)
3820     {
3821       SubjectElementaryNode* elem = dynamic_cast<SubjectElementaryNode*>(_parent);
3822       if (elem) elem->removePort(this);
3823     }
3824 }
3825
3826 bool SubjectOutputPort::setValue(std::string value)
3827 {
3828   DEBTRACE("SubjectOutputPort::setValue " << value);
3829   Proc *proc = GuiContext::getCurrent()->getProc();
3830   CommandSetOutPortValue *command =
3831     new CommandSetOutPortValue(proc->getChildName(getPort()->getNode()), getName(), value);
3832   if (command->execute())
3833     {
3834       GuiContext::getCurrent()->getInvoc()->add(command);
3835       return true;
3836     }
3837   else delete command;
3838   return false;
3839 }
3840
3841 // ----------------------------------------------------------------------------
3842
3843 SubjectInputDataStreamPort::SubjectInputDataStreamPort(YACS::ENGINE::InputDataStreamPort *port,
3844                                                        Subject *parent)
3845   : SubjectDataPort(port, parent), _inputDataStreamPort(port)
3846 {
3847 }
3848
3849 SubjectInputDataStreamPort::~SubjectInputDataStreamPort()
3850 {
3851   DEBTRACE("SubjectInputDataStreamPort::~SubjectInputDataStreamPort " << getName());
3852 }
3853
3854 std::map<std::string, std::string> SubjectInputDataStreamPort::getProperties()
3855 {
3856   return _inputDataStreamPort->getProperties();
3857 }
3858
3859 std::vector<std::string> SubjectInputDataStreamPort::knownProperties()
3860 {
3861   std::vector<std::string> props;
3862   props.push_back("StorageLevel");
3863   //props.push_back("DependencyType");
3864   props.push_back("DateCalSchem");
3865   props.push_back("Alpha");
3866   props.push_back("DeltaT");
3867   props.push_back("InterpolationSchem");
3868   props.push_back("ExtrapolationSchem");
3869   return props;
3870 }
3871
3872 bool SubjectInputDataStreamPort::setProperties(std::map<std::string, std::string> properties)
3873 {
3874   Proc *proc = GuiContext::getCurrent()->getProc();
3875   CommandSetDSPortProperties *command =
3876     new CommandSetDSPortProperties(proc->getChildName(getPort()->getNode()), getName(), true, properties);
3877   if (command->execute())
3878     {
3879       GuiContext::getCurrent()->getInvoc()->add(command);
3880       return true;
3881     }
3882   else delete command;
3883   return false;
3884 }
3885
3886 void SubjectInputDataStreamPort::clean(Command *command)
3887 {
3888   if (_askRegisterUndo)
3889     {
3890       _askRegisterUndo = false;
3891       registerUndoDestroy();
3892     }
3893   localclean(command);
3894   SubjectDataPort::clean(command);
3895 }
3896
3897 void SubjectInputDataStreamPort::localclean(Command *command)
3898 {
3899   DEBTRACE("SubjectInputDataStreamPort::localClean ");
3900 }
3901
3902 void SubjectInputDataStreamPort::registerUndoDestroy()
3903 {
3904   DEBTRACE("SubjectInputDataStreamPort::registerUndoDestroy");
3905   SubjectDataPort::registerUndoDestroy();
3906   map<string,string> properties = getProperties();
3907   if (properties.empty())
3908     return;
3909   Proc *proc = GuiContext::getCurrent()->getProc();
3910   SubjectNode *sno = dynamic_cast<SubjectNode*>(getParent());
3911   YASSERT(sno);
3912   Node *node = sno->getNode();
3913   string nodeName = proc->getChildName(node);
3914   string portName = getName();
3915   Command *command = new CommandSetDSPortProperties(nodeName, portName, true, properties);
3916   GuiContext::getCurrent()->getInvoc()->add(command);
3917 }
3918
3919 // ----------------------------------------------------------------------------
3920
3921 SubjectOutputDataStreamPort::SubjectOutputDataStreamPort(YACS::ENGINE::OutputDataStreamPort *port,
3922                                                          Subject *parent)
3923   : SubjectDataPort(port, parent), _outputDataStreamPort(port)
3924 {
3925 }
3926
3927 SubjectOutputDataStreamPort::~SubjectOutputDataStreamPort()
3928 {
3929   DEBTRACE("SubjectOutputDataStreamPort::~SubjectOutputDataStreamPort " << getName());
3930 }
3931
3932 std::map<std::string, std::string> SubjectOutputDataStreamPort::getProperties()
3933 {
3934   return _outputDataStreamPort->getProperties();
3935 }
3936
3937 bool SubjectOutputDataStreamPort::setProperties(std::map<std::string, std::string> properties)
3938 {
3939   Proc *proc = GuiContext::getCurrent()->getProc();
3940   CommandSetDSPortProperties *command =
3941     new CommandSetDSPortProperties(proc->getChildName(getPort()->getNode()), getName(), false, properties);
3942   if (command->execute())
3943     {
3944       GuiContext::getCurrent()->getInvoc()->add(command);
3945       return true;
3946     }
3947   else delete command;
3948   return false;
3949 }
3950
3951 void SubjectOutputDataStreamPort::clean(Command *command)
3952 {
3953   if (_askRegisterUndo)
3954     {
3955       _askRegisterUndo = false;
3956       registerUndoDestroy();
3957     }
3958   localclean(command);
3959   SubjectDataPort::clean(command);
3960 }
3961
3962 void SubjectOutputDataStreamPort::localclean(Command *command)
3963 {
3964   DEBTRACE("SubjectOutputDataStreamPort::localClean ");
3965 }
3966
3967 void SubjectOutputDataStreamPort::registerUndoDestroy()
3968 {
3969   DEBTRACE("SubjectOutputDataStreamPort::registerUndoDestroy");
3970   SubjectDataPort::registerUndoDestroy();
3971   map<string,string> properties = getProperties();
3972   if (properties.empty())
3973     return;
3974   Proc *proc = GuiContext::getCurrent()->getProc();
3975   SubjectNode *sno = dynamic_cast<SubjectNode*>(getParent());
3976   YASSERT(sno);
3977   Node *node = sno->getNode();
3978   string nodeName = proc->getChildName(node);
3979   string portName = getName();
3980   Command *command = new CommandSetDSPortProperties(nodeName, portName, false, properties);
3981   GuiContext::getCurrent()->getInvoc()->add(command);
3982 }
3983
3984 // ----------------------------------------------------------------------------
3985
3986 SubjectLink::SubjectLink(SubjectNode* subOutNode,
3987                          SubjectDataPort* outPort,
3988                          SubjectNode* subInNode,
3989                          SubjectDataPort* inPort,
3990                          Subject *parent)
3991   : Subject(parent),
3992     _subOutNode(subOutNode), _outPort(outPort), _subInNode(subInNode), _inPort(inPort)
3993 {
3994   _name = "";
3995   ComposedNode *cla = ComposedNode::getLowestCommonAncestor(_subOutNode->getNode()->getFather(),
3996                                                             _subInNode->getNode()->getFather());
3997   DEBTRACE(_subOutNode->getName() << "." << _outPort->getName());
3998   DEBTRACE(_subInNode->getName() << "." << _inPort->getName());
3999   DEBTRACE(cla->getName());
4000   _name += cla->getChildName(_subOutNode->getNode());
4001   _name += "." + _outPort->getName();
4002   _name += "->";
4003   _name += cla->getChildName(_subInNode->getNode());
4004   _name += "." + _inPort->getName();
4005   DEBTRACE("SubjectLink::SubjectLink " << _name);
4006 }
4007
4008 SubjectLink::~SubjectLink()
4009 {
4010   DEBTRACE("SubjectLink::~SubjectLink " << getName());
4011   _inPort->update(UPDATE,DATALINK,_outPort);
4012   _outPort->update(UPDATE,DATALINK,_inPort);
4013 }
4014
4015 void SubjectLink::clean(Command *command)
4016 {
4017   if (_askRegisterUndo)
4018     {
4019       _askRegisterUndo = false;
4020       registerUndoDestroy();
4021     }
4022   localclean(command);
4023   Subject::clean(command);
4024 }
4025
4026 void SubjectLink::localclean(Command *command)
4027 {
4028   DEBTRACE("SubjectLink::localClean ");
4029   if (_parent)
4030     {
4031       DEBTRACE("clean link: " << _parent->getName() << " " << getName());
4032       SubjectComposedNode* father = dynamic_cast<SubjectComposedNode*>(_parent);
4033       YASSERT(father);
4034       father->removeLink(this); // --- clean subjects first
4035       _cla = dynamic_cast<ComposedNode*>(father->getNode());
4036       YASSERT(_cla);
4037       _outp = dynamic_cast<OutPort*>(_outPort->getPort());
4038       YASSERT(_outp);
4039       _inp = dynamic_cast<InPort*>(_inPort->getPort());
4040       YASSERT(_inp);
4041       if (isDestructible())
4042         _cla->edRemoveLink(_outp, _inp);
4043     }
4044 }
4045
4046 std::string SubjectLink::getName()
4047 {
4048   return _name;
4049 }
4050
4051 std::map<std::string, std::string> SubjectLink::getProperties()
4052 {
4053   return getSubjectInPort()->getProperties();
4054 }
4055
4056 std::vector<std::string> SubjectLink::knownProperties()
4057 {
4058   return getSubjectInPort()->knownProperties();
4059 }
4060
4061 bool SubjectLink::setProperties(std::map<std::string, std::string> properties)
4062 {
4063   Proc *proc = GuiContext::getCurrent()->getProc();
4064   CommandSetLinkProperties *command =
4065     new CommandSetLinkProperties(proc->getChildName(getSubjectOutPort()->getPort()->getNode()), getSubjectOutPort()->getName(), 
4066                                  proc->getChildName(getSubjectInPort()->getPort()->getNode()), getSubjectInPort()->getName(), 
4067                                  properties);
4068   if (command->execute())
4069     {
4070       GuiContext::getCurrent()->getInvoc()->add(command);
4071       return true;
4072     }
4073   else delete command;
4074   return false;
4075 }
4076
4077 void SubjectLink::registerUndoDestroy()
4078 {
4079   DEBTRACE("SubjectLink::registerUndoDestroy");
4080   Proc *proc = GuiContext::getCurrent()->getProc();
4081   Node *outn = getSubjectOutNode()->getNode();
4082   Node *inn = getSubjectInNode()->getNode();
4083   DataPort *outp = getSubjectOutPort()->getPort();
4084   DataPort *inp = getSubjectInPort()->getPort();
4085   CommandAddLink *command = new CommandAddLink(proc->getChildName(outn),
4086                                                outp->getName(),
4087                                                getSubjectOutPort()->getType(),
4088                                                proc->getChildName(inn),
4089                                                inp->getName(),
4090                                                getSubjectInPort()->getType(),
4091                                                false);
4092   GuiContext::getCurrent()->getInvoc()->add(command);
4093
4094   map<string, string> properties = getProperties();
4095   if (properties.empty())
4096     return;
4097
4098   CommandSetLinkProperties *command2 = new CommandSetLinkProperties(proc->getChildName(outn),
4099                                                                     outp->getName(),
4100                                                                     proc->getChildName(inn),
4101                                                                     inp->getName(),
4102                                                                     properties);
4103   GuiContext::getCurrent()->getInvoc()->add(command2); 
4104 }
4105
4106 // ----------------------------------------------------------------------------
4107
4108 SubjectControlLink::SubjectControlLink(SubjectNode* subOutNode,
4109                                        SubjectNode* subInNode,
4110                                        Subject *parent)
4111   : Subject(parent),
4112     _subOutNode(subOutNode), _subInNode(subInNode)
4113 {
4114   _name = "";
4115   ComposedNode *cla = ComposedNode::getLowestCommonAncestor(_subOutNode->getNode()->getFather(),
4116                                                             _subInNode->getNode()->getFather());
4117   DEBTRACE(_subOutNode->getName());
4118   DEBTRACE(_subInNode->getName());
4119   DEBTRACE(cla->getName());
4120   _name += cla->getChildName(_subOutNode->getNode());
4121   _name += "-->>";
4122   _name += cla->getChildName(_subInNode->getNode());
4123   DEBTRACE("SubjectControlLink::SubjectControlLink " << _name);
4124 }
4125
4126 SubjectControlLink::~SubjectControlLink()
4127 {
4128   DEBTRACE("SubjectControlLink::~SubjectControlLink " << getName());
4129   if (isDestructible())
4130     {
4131       try
4132         {
4133
4134           _cla->edRemoveCFLink(_subOutNode->getNode(), _subInNode->getNode());
4135         }
4136       catch (YACS::Exception &e)
4137         {
4138           DEBTRACE("------------------------------------------------------------------------------");
4139           DEBTRACE("SubjectControlLink::~SubjectControlLink: edRemoveLink YACS exception " << e.what());
4140           DEBTRACE("------------------------------------------------------------------------------");
4141         }
4142     }
4143 }
4144
4145 void SubjectControlLink::clean(Command *command)
4146 {
4147   if (_askRegisterUndo)
4148     {
4149       _askRegisterUndo = false;
4150       registerUndoDestroy();
4151     }
4152   localclean(command);
4153   Subject::clean(command);
4154 }
4155
4156 void SubjectControlLink::localclean(Command *command)
4157 {
4158   DEBTRACE("SubjectControlLink::localClean ");
4159   if (_parent)
4160     {
4161       DEBTRACE("clean control link: " << _parent->getName() << " " << getName());
4162       SubjectComposedNode* father = dynamic_cast<SubjectComposedNode*>(_parent);
4163       YASSERT(father);
4164       father->removeControlLink(this); // --- clean subjects first
4165       _cla = dynamic_cast<ComposedNode*>(father->getNode());
4166       YASSERT(_cla);
4167     }
4168 }
4169
4170 std::string SubjectControlLink::getName()
4171 {
4172   return _name;
4173 }
4174
4175 void SubjectControlLink::registerUndoDestroy()
4176 {
4177   DEBTRACE("SubjectControlLink::registerUndoDestroy");
4178   Proc *proc = GuiContext::getCurrent()->getProc();
4179   Node *outn = getSubjectOutNode()->getNode();
4180   Node *inn = getSubjectInNode()->getNode();
4181   CommandAddControlLink *command = new CommandAddControlLink(proc->getChildName(outn),
4182                                                              proc->getChildName(inn));
4183   GuiContext::getCurrent()->getInvoc()->add(command);
4184 }
4185
4186 // ----------------------------------------------------------------------------
4187
4188 SubjectComponent::SubjectComponent(YACS::ENGINE::ComponentInstance* component, Subject *parent)
4189   : Subject(parent), _compoInst(component)
4190 {
4191   _compoInst->incrRef();
4192   _subRefContainer = 0;
4193   _subServiceSet.clear();
4194   _subReferenceMap.clear();
4195 }
4196
4197 SubjectComponent::~SubjectComponent()
4198 {
4199   Proc* aProc = GuiContext::getCurrent()->getProc();
4200   if ( aProc )
4201   {
4202     aProc->componentInstanceMap.erase(_compoInst->getInstanceName());
4203     GuiContext::getCurrent()->_mapOfSubjectComponent.erase(_compoInst);
4204   }
4205   _compoInst->decrRef();
4206 }
4207
4208 void SubjectComponent::clean(Command *command)
4209 {
4210   if (_askRegisterUndo)
4211     {
4212       _askRegisterUndo = false;
4213       registerUndoDestroy();
4214     }
4215   localclean(command);
4216   Subject::clean(command);
4217 }
4218
4219 void SubjectComponent::localclean(Command *command)
4220 {
4221   DEBTRACE("SubjectComponent::localClean " << this);
4222   Proc* aProc = GuiContext::getCurrent()->getProc();
4223   if ( aProc )
4224   {
4225     std::map<Node*, SubjectNode*>::iterator it = GuiContext::getCurrent()->_mapOfSubjectNode.begin();
4226     std::list<SubjectNode*> services;
4227     for ( ; it!=GuiContext::getCurrent()->_mapOfSubjectNode.end(); it++ )
4228       {
4229         if(ServiceNode* service=dynamic_cast<ServiceNode*>((*it).first))
4230           {
4231             if ( service->getComponent() == _compoInst )
4232               {
4233                 services.push_back((*it).second);
4234               }
4235           }
4236       }
4237     while(!services.empty())
4238       {
4239         SubjectNode* son=services.front();
4240         services.pop_front();
4241         Subject* parent=son->getParent();
4242 //         parent->update(REMOVE,son->getType(),son);
4243         parent->erase(son);
4244         parent->update(REMOVE,0,0);
4245       }
4246       
4247     Container* container = _compoInst->getContainer();
4248     if (!container) return;
4249     SubjectContainer *subContainer;
4250     YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(container));
4251     subContainer = GuiContext::getCurrent()->_mapOfSubjectContainer[container];
4252     subContainer->removeSubComponentFromSet(this);
4253   }
4254 }
4255
4256 std::string SubjectComponent::getName()
4257 {
4258   return _compoInst->getInstanceName();
4259 }
4260
4261 std::pair<std::string, int> SubjectComponent::getKey()
4262 {
4263   std::pair<std::string, int> key = std::pair<std::string, int>(_compoInst->getCompoName(), _compoInst->getNumId());
4264   return key;
4265 }
4266
4267 YACS::ENGINE::ComponentInstance* SubjectComponent::getComponent() const
4268 {
4269   return _compoInst;
4270 }
4271
4272 /*!
4273  *  When loading scheme from file, get the container associated to the component, if any,
4274  *  and create the corresponding subject.
4275  */
4276 void SubjectComponent::setContainer()
4277 {
4278   DEBTRACE("SubjectComponent::setContainer " << getName());
4279   Container* container = _compoInst->getContainer();
4280   if (container)
4281     {
4282       SubjectContainer *subContainer;
4283       if (GuiContext::getCurrent()->_mapOfSubjectContainer.count(container))
4284         subContainer = GuiContext::getCurrent()->_mapOfSubjectContainer[container];
4285       else
4286         subContainer = 
4287           GuiContext::getCurrent()->getSubjectProc()->addSubjectContainer(container, container->getName());
4288       addSubjectReference(subContainer);
4289       if (_subRefContainer)
4290         subContainer->moveComponent(_subRefContainer);
4291       else
4292         _subRefContainer = subContainer->attachComponent(this);
4293       notifyServicesChange(ASSOCIATE, CONTAINER, subContainer);
4294     }
4295 }
4296
4297 bool SubjectComponent::associateToContainer(SubjectContainer* subcont)
4298 {
4299   DEBTRACE("SubjectComponent::associateToContainer " << getName() << " " << subcont->getName());
4300   CommandAssociateComponentToContainer *command =
4301     new CommandAssociateComponentToContainer(_compoInst->getInstanceName(), subcont->getName());
4302   if (command->execute())
4303     {
4304       if (!GuiContext::getCurrent()->isLoading()) // do not register command when loading a schema
4305         GuiContext::getCurrent()->getInvoc()->add(command);
4306       else delete command;
4307       return true;
4308     }
4309   else delete command;
4310   return false;
4311 }
4312
4313 SubjectReference* SubjectComponent::attachService(SubjectServiceNode* service)
4314 {
4315   DEBTRACE("SubjectComponent::attachService");
4316   SubjectReference *son = new SubjectReference(service, this);
4317   _subServiceSet.insert(service);
4318   _subReferenceMap[service] = son;
4319   update(ADDCHILDREF, SALOMENODE, son);
4320   return son;
4321 }
4322
4323 void SubjectComponent::detachService(SubjectServiceNode* service)
4324 {
4325   DEBTRACE("SubjectComponent::detachService");
4326   YASSERT(_subReferenceMap.count(service));
4327   SubjectReference *reference = _subReferenceMap[service];
4328   update(REMOVECHILDREF, SALOMENODE, reference);
4329   _subServiceSet.erase(service);
4330   _subReferenceMap.erase(service);
4331   service->removeSubRefComponent();
4332   erase(reference);
4333 }
4334
4335 void SubjectComponent::moveService(SubjectReference* reference)
4336 {
4337   DEBTRACE("SubjectComponent::moveService");
4338   SubjectComponent* oldcomp = dynamic_cast<SubjectComponent*>(reference->getParent());
4339   YASSERT(oldcomp);
4340
4341   SubjectServiceNode* service = dynamic_cast<SubjectServiceNode*>(reference->getReference());
4342   oldcomp->removeSubServiceFromSet(service);
4343   _subServiceSet.insert(service);
4344   _subReferenceMap[service] = reference;
4345   oldcomp->update(CUT, SALOMENODE, reference);
4346   reference->reparent(this);
4347   update(PASTE, SALOMENODE, reference);
4348   if (!oldcomp->hasServices())
4349     Subject::erase(oldcomp);
4350 }
4351
4352 void SubjectComponent::removeSubServiceFromSet(SubjectServiceNode *service)
4353 {
4354   DEBTRACE("SubjectComponent::removeSubServiceFromSet " << getName() << " " << service->getName());
4355   _subServiceSet.erase(service);
4356   _subReferenceMap.erase(service);
4357 }
4358
4359 void SubjectComponent::notifyServicesChange(GuiEvent event, int type, Subject* son)
4360 {
4361   DEBTRACE("SubjectComponent::notifyServicesChange");
4362   set<SubjectServiceNode*>::iterator it = _subServiceSet.begin();
4363   for(; it != _subServiceSet.end(); ++it)
4364     {
4365       (*it)->update(event, type, son);
4366     }
4367 }
4368
4369 bool SubjectComponent::setProperties(std::map<std::string, std::string> properties)
4370 {
4371   CommandSetComponentInstanceProperties *command = new CommandSetComponentInstanceProperties(getName(), properties);
4372   if (command->execute())
4373     {
4374       GuiContext::getCurrent()->getInvoc()->add(command);
4375       return true;
4376     }
4377   else delete command;
4378   return false;
4379 }
4380
4381 std::map<std::string, std::string> SubjectComponent::getProperties()
4382 {
4383   return _compoInst->getProperties();
4384 }
4385
4386 // ----------------------------------------------------------------------------
4387
4388 SubjectContainer::SubjectContainer(YACS::ENGINE::Container* container, Subject *parent)
4389   : Subject(parent), _container(container)
4390 {
4391   _subComponentSet.clear();
4392   _subReferenceMap.clear();
4393 }
4394
4395 SubjectContainer::~SubjectContainer()
4396 {
4397   DEBTRACE("SubjectContainer::~SubjectContainer");
4398   Proc* aProc = GuiContext::getCurrent()->getProc();
4399   if ( aProc )
4400   {
4401     map<ComponentInstance*,SubjectComponent*> mapOfSubjectComponentCpy
4402       = GuiContext::getCurrent()->_mapOfSubjectComponent;
4403     map<ComponentInstance*,SubjectComponent*>::iterator it = mapOfSubjectComponentCpy.begin();
4404     for ( ; it!=mapOfSubjectComponentCpy.end(); it++ )
4405       if ( (*it).first && (*it).first->getContainer() == _container )
4406       {
4407         (*it).first->setContainer(0);
4408         GuiContext::getCurrent()->getSubjectProc()->destroy((*it).second);
4409       }
4410
4411     GuiContext::getCurrent()->_mapOfSubjectContainer.erase(_container);
4412     aProc->removeContainer(_container);
4413   }
4414 }
4415
4416 std::map<std::string, std::string> SubjectContainer::getProperties()
4417 {
4418   return _container->getProperties();
4419 }
4420
4421 bool SubjectContainer::setProperties(std::map<std::string, std::string> properties)
4422 {
4423   CommandSetContainerProperties *command = new CommandSetContainerProperties(getName(), properties);
4424   if (command->execute())
4425     {
4426       GuiContext::getCurrent()->getInvoc()->add(command);
4427       return true;
4428     }
4429   else delete command;
4430   return false;
4431 }
4432
4433 bool SubjectContainer::setName(std::string name)
4434 {
4435   DEBTRACE("SubjectContainer::setName " << name);
4436   if (name == getName())
4437     return true;
4438   CommandRenameContainer* command = new CommandRenameContainer(getName(), name);
4439   if (command->execute())
4440     {
4441       GuiContext::getCurrent()->getInvoc()->add(command);
4442       return true;
4443     }
4444   else delete command;
4445   return false;
4446 }
4447
4448 SubjectReference* SubjectContainer::attachComponent(SubjectComponent* component)
4449 {
4450   DEBTRACE("SubjectContainer::attachComponent");
4451   SubjectReference *son = new SubjectReference(component, this);
4452   _subComponentSet.insert(component);
4453   _subReferenceMap[component] = son;
4454   update(ADDCHILDREF, COMPONENT, son);
4455   return son;
4456 }
4457
4458 void SubjectContainer::detachComponent(SubjectComponent* component)
4459 {
4460   DEBTRACE("SubjectContainer::detachComponent");
4461   YASSERT(_subReferenceMap.count(component));
4462   SubjectReference *reference = _subReferenceMap[component];
4463   update(REMOVECHILDREF, COMPONENT, reference);
4464   _subComponentSet.erase(component);
4465   _subReferenceMap.erase(component);
4466   erase(reference);
4467 }
4468
4469 void SubjectContainer::moveComponent(SubjectReference* reference)
4470 {
4471   DEBTRACE("SubjectContainer::moveComponent");
4472   SubjectContainer* oldcont = dynamic_cast<SubjectContainer*>(reference->getParent());
4473   YASSERT(oldcont);
4474   SubjectComponent* component = dynamic_cast<SubjectComponent*>(reference->getReference());
4475   _subComponentSet.insert(component);
4476   _subReferenceMap[component] = reference;
4477   oldcont->removeSubComponentFromSet(component);
4478   oldcont->update(CUT, COMPONENT, reference);
4479   reference->reparent(this);
4480   update(PASTE, COMPONENT, reference);
4481 }
4482
4483 void SubjectContainer::removeSubComponentFromSet(SubjectComponent *component)
4484 {
4485   DEBTRACE("SubjectContainer::removeSubComponentFromSet");
4486   _subComponentSet.erase(component);
4487   _subReferenceMap.erase(component);
4488 }
4489
4490 void SubjectContainer::notifyComponentsChange(GuiEvent event, int type, Subject* son)
4491 {
4492   DEBTRACE("SubjectContainer::notifyComponentsChange");
4493   set<SubjectComponent*>::iterator it = _subComponentSet.begin();
4494   for(; it != _subComponentSet.end(); ++it)
4495     {
4496       (*it)->update(event, type, son);
4497       (*it)->notifyServicesChange(event, type, son);
4498     }
4499 }
4500
4501
4502 void SubjectContainer::clean(Command *command)
4503 {
4504   if (_askRegisterUndo)
4505     {
4506       _askRegisterUndo = false;
4507       registerUndoDestroy();
4508     }
4509   localclean(command);
4510   Subject::clean(command);
4511 }
4512
4513 void SubjectContainer::localclean(Command *command)
4514 {
4515   DEBTRACE("SubjectContainer::localClean ");
4516   Proc* aProc = GuiContext::getCurrent()->getProc();
4517   if ( aProc )
4518   {
4519     SubjectComponent* compo;
4520     map<ComponentInstance*,SubjectComponent*>::iterator it = GuiContext::getCurrent()->_mapOfSubjectComponent.begin();
4521     std::list<SubjectComponent*> compos;
4522     for ( ; it!=GuiContext::getCurrent()->_mapOfSubjectComponent.end(); it++ )
4523       if ( (*it).first && (*it).first->getContainer() == _container )
4524       {
4525         compo=(*it).second;
4526         (*it).first->setContainer(0);
4527         compos.push_back((*it).second);
4528       }
4529     while(!compos.empty())
4530       {
4531         compo=compos.front();
4532         compos.pop_front();
4533         GuiContext::getCurrent()->getSubjectProc()->update(REMOVE,compo->getType(),compo);
4534         GuiContext::getCurrent()->getSubjectProc()->erase(compo);
4535       }
4536   }
4537 }
4538
4539 std::string SubjectContainer::getName()
4540 {
4541   return _container->getName();
4542 }
4543
4544 YACS::ENGINE::Container* SubjectContainer::getContainer() const
4545 {
4546   return _container;
4547 }
4548
4549 void SubjectContainer::registerUndoDestroy()
4550 {
4551   DEBTRACE("SubjectContainer::registerUndoDestroy");
4552   Command *command = new CommandAddContainer(getName(),"");
4553   GuiContext::getCurrent()->getInvoc()->add(command);
4554 }
4555
4556 // ----------------------------------------------------------------------------
4557
4558 SubjectDataType::SubjectDataType(YACS::ENGINE::TypeCode *typeCode, Subject *parent, std::string alias)
4559   : Subject(parent), _typeCode(typeCode), _alias(alias)
4560 {
4561 }
4562
4563 SubjectDataType::~SubjectDataType()
4564 {
4565 }
4566
4567 void SubjectDataType::clean(Command *command)
4568 {
4569   if (_askRegisterUndo)
4570     {
4571       _askRegisterUndo = false;
4572       registerUndoDestroy();
4573     }
4574   localclean(command);
4575   Subject::clean(command);
4576 }
4577
4578 void SubjectDataType::localclean(Command *command)
4579 {
4580   DEBTRACE("SubjectDataType::localClean ");
4581 }
4582
4583 std::string SubjectDataType::getName()
4584 {
4585   return _typeCode->name();
4586 }
4587
4588 std::string SubjectDataType::getAlias()
4589 {
4590   return _alias;
4591 }
4592
4593 YACS::ENGINE::TypeCode* SubjectDataType::getTypeCode()
4594 {
4595   return _typeCode;
4596 }
4597
4598 // ----------------------------------------------------------------------------