f7592693dc6b6a5a738760413d88947a0ba19d73
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / ports_management.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014 - Scilab Enterprises - Paul Bignier
4  *  Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
5  *
6  *  This file must be used under the terms of the CeCILL.
7  *  This source file is licensed as described in the file COPYING, which
8  *  you should have received as part of this distribution.  The terms
9  *  are also available at
10  *  http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11  *
12  */
13
14 #ifndef PORTS_MANAGEMENT_HXX_
15 #define PORTS_MANAGEMENT_HXX_
16
17 #include <cmath>
18
19 #include <deque>
20 #include <string>
21 #include <vector>
22 #include <algorithm>
23 #include <iterator>
24 #include <cassert>
25
26 #include "internal.hxx"
27 #include "bool.hxx"
28 #include "double.hxx"
29 #include "string.hxx"
30
31 #include "utilities.hxx"
32 #include "Controller.hxx"
33 #include "controller_helpers.hxx"
34 #include "model/Port.hxx"
35
36 extern "C" {
37 #include "sci_malloc.h"
38 #include "charEncoding.h"
39 #include "localization.h"
40 }
41
42 namespace org_scilab_modules_scicos
43 {
44 namespace view_scilab
45 {
46
47 /*
48  * Utilities function to emit the error messages
49  */
50 template<object_properties_t p>
51 std::string adapterName(const object_properties_t port_kind)
52 {
53     switch (p)
54     {
55         case CONNECTED_SIGNALS:
56         case IMPLICIT:
57         case LABEL:
58         case STYLE:
59             return "graphics";
60         case DATATYPE_ROWS:
61         case DATATYPE_COLS:
62         case DATATYPE_TYPE:
63         case FIRING:
64             return "model";
65     }
66 }
67
68 template<object_properties_t p>
69 std::string adapterFieldName(const object_properties_t port_kind)
70 {
71     std::string postfix;
72     switch (p)
73     {
74         case CONNECTED_SIGNALS:
75         {
76             switch (port_kind)
77             {
78                 case INPUTS:
79                     return "pin";
80                 case OUTPUTS:
81                     return "pout";
82                 case EVENT_INPUTS:
83                     return "pein";
84                 case EVENT_OUTPUTS:
85                     return "peout";
86                 default:
87                     break;
88             }
89         }
90         break;
91         case IMPLICIT:
92             postfix = "_implicit";
93             break;
94         case LABEL:
95             postfix = "_label";
96             break;
97         case STYLE:
98             postfix = "_style";
99             break;
100         case DATATYPE_TYPE:
101             postfix = "typ";
102             break;
103         case DATATYPE_ROWS:
104             postfix = "2";
105             break;
106         case DATATYPE_COLS:
107             break;
108         case FIRING:
109             return "firing";
110         default:
111             break;
112     }
113
114     std::string prefix;
115     switch (port_kind)
116     {
117         case INPUTS:
118             prefix = "in";
119             break;
120         case OUTPUTS:
121             prefix = "out";
122             break;
123         case EVENT_INPUTS:
124             prefix = "evtin";
125             break;
126         case EVENT_OUTPUTS:
127             prefix = "evtout";
128             break;
129         default:
130             break;
131     }
132
133     return prefix + postfix;
134 }
135
136 /*
137  * Return a Scilab encoded value for a property.
138  */
139 template<typename Adaptor, object_properties_t p>
140 types::InternalType* get_ports_property(const Adaptor& adaptor, const object_properties_t port_kind, const Controller& controller)
141 {
142     ScicosID adaptee = adaptor.getAdaptee()->id();
143
144     // Retrieve the identifiers
145     std::vector<ScicosID> ids;
146     controller.getObjectProperty(adaptee, BLOCK, port_kind, ids);
147
148     // Translate identifiers: shared variables
149     int i = 0;
150     size_t datatypeIndex = -1;
151     // Translate identifiers to return values
152     switch (p)
153     {
154         case STYLE:
155         case LABEL:
156         {
157             if (ids.empty())
158             {
159                 return new types::String(L"");
160             }
161             types::String* o = new types::String((int)ids.size(), 1);
162             for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
163             {
164                 std::string s;
165                 controller.getObjectProperty(*it, PORT, p, s);
166                 o->set(i, s.data());
167             }
168             return o;
169         }
170         case DATATYPE_TYPE:
171             // The type defaults to [1] if no port has been defined
172             if (ids.empty())
173             {
174                 return new types::Double(1);
175             }
176             datatypeIndex++;
177             // no break
178         case DATATYPE_COLS:
179             datatypeIndex++;
180             // no break
181         case DATATYPE_ROWS:
182         {
183             datatypeIndex++;
184             double* data;
185             types::Double* o = new types::Double((int)ids.size(), 1, &data);
186             for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
187             {
188                 std::vector<int> v;
189                 controller.getObjectProperty(*it, PORT, DATATYPE, v);
190                 data[i] = v[datatypeIndex];
191             }
192             return o;
193         }
194         case FIRING:
195         {
196             double* data;
197             types::Double* o = new types::Double((int)ids.size(), 1, &data);
198             for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
199             {
200                 controller.getObjectProperty(*it, PORT, p, data[i]);
201             }
202             return o;
203         }
204         case IMPLICIT:
205         {
206             if (ids.size() == 0)
207             {
208                 // When no port is present, return an empty matrix
209                 return types::Double::Empty();
210             }
211
212             types::String* o = new types::String((int)ids.size(), 1);
213             for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
214             {
215                 bool v;
216                 controller.getObjectProperty(*it, PORT, p, v);
217                 o->set(i, (v == false) ? L"E" : L"I");
218             }
219             return o;
220         }
221         case CONNECTED_SIGNALS:
222         {
223             double* v;
224             types::Double* o = new types::Double((int)ids.size(), 1, &v);
225
226             ScicosID diagram;
227             controller.getObjectProperty(adaptee, BLOCK, PARENT_DIAGRAM, diagram);
228
229             std::vector<ScicosID> children;
230             if (diagram != 0)
231             {
232                 controller.getObjectProperty(diagram, DIAGRAM, CHILDREN, children);
233             }
234
235             for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
236             {
237                 ScicosID id;
238                 controller.getObjectProperty(*it, PORT, p, id);
239
240                 v[i] = 0;
241
242                 if (id == 0)
243                 {
244                     // Unconnected port, no need to search in 'children'
245                 }
246                 else
247                 {
248                     std::vector<ScicosID>::iterator found = std::find(children.begin(), children.end(), id);
249
250                     if (found != children.end())
251                     {
252                         v[i] = static_cast<double>(std::distance(children.begin(), found)) + 1;
253                     }
254                 }
255             }
256             return o;
257         }
258         default:
259             return 0;
260     }
261 }
262
263 /*
264  * Set a Scilab encoded values as a property.
265  *
266  * \note this method will ignore or return false if one of the ports does not exist, depending on the property setted.
267  */
268 template<typename Adaptor, object_properties_t p>
269 bool set_ports_property(const Adaptor& adaptor, const object_properties_t port_kind, Controller& controller, types::InternalType* v)
270 {
271     ScicosID adaptee = adaptor.getAdaptee()->id();
272
273     // Retrieve the ports identifiers
274     std::vector<ScicosID> ids;
275     controller.getObjectProperty(adaptee, BLOCK, port_kind, ids);
276
277     if (v->getType() == types::InternalType::ScilabString)
278     {
279         types::String* current = v->getAs<types::String>();
280
281         // Translate identifiers: shared variables
282         int i = 0;
283         // Translate identifiers from values
284         switch (p)
285         {
286             case STYLE:
287             case LABEL:
288             {
289                 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
290                 {
291                     char* c_str = NULL;
292                     if (i >= current->getSize())
293                     {
294                         // If the input isn't large enough, fill each port with empty strings
295                         c_str = wide_string_to_UTF8(L"");
296                     }
297                     else
298                     {
299                         c_str = wide_string_to_UTF8(current->get(i));
300                     }
301                     controller.setObjectProperty(*it, PORT, p, std::string(c_str));
302                     FREE(c_str);
303                 }
304                 return true;
305             }
306             case IMPLICIT:
307             {
308                 if (current->getSize() < static_cast<int>(ids.size()))
309                 {
310                     std::string adapter = adapterName<p>(port_kind);
311                     std::string field = adapterFieldName<p>(port_kind);
312                     get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), adapter.data(), field.data(), ids.size(), 1);
313                     return false;
314                 }
315
316                 std::wstring E = L"E";
317                 std::wstring I = L"I";
318                 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
319                 {
320                     if (current->get(i) == I)
321                     {
322                         controller.setObjectProperty(*it, PORT, p, true);
323                     }
324                     else if (current->get(i) == E)
325                     {
326                         controller.setObjectProperty(*it, PORT, p, false);
327                     }
328                     else
329                     {
330                         std::string adapter = adapterName<p>(port_kind);
331                         std::string field = adapterFieldName<p>(port_kind);
332                         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s: %s or %s vector expected.\n"), adapter.data(), field.data(), "'E'", "'I'");
333                         return false;
334                     }
335                 }
336                 return true;
337             }
338             default:
339                 std::string adapter = adapterName<p>(port_kind);
340                 std::string field = adapterFieldName<p>(port_kind);
341                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s .\n"), adapter.data(), field.data());
342                 return false;
343         }
344     }
345     else if (v->getType() == types::InternalType::ScilabDouble)
346     {
347         types::Double* current = v->getAs<types::Double>();
348
349         // Translate identifiers: shared variables
350         int i = 0;
351         size_t datatypeIndex = -1;
352         // Translate identifiers from values
353         switch (p)
354         {
355             case FIRING:
356                 if (current->isEmpty())
357                 {
358                     return true;
359                 }
360
361                 if (current->getSize() < static_cast<int>(ids.size()))
362                 {
363                     std::string adapter = adapterName<p>(port_kind);
364                     std::string field = adapterFieldName<p>(port_kind);
365                     get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), adapter.data(), field.data(), ids.size(), 1);
366                     return false;
367                 }
368
369                 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
370                 {
371                     double firing = current->get(i);
372
373                     controller.setObjectProperty(*it, PORT, p, firing);
374                 }
375                 return true;
376             case STYLE:
377             case LABEL:
378                 // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update
379                 return true;
380
381             case DATATYPE_TYPE:
382                 datatypeIndex++;
383                 // no break
384             case DATATYPE_COLS:
385                 datatypeIndex++;
386                 // no break
387             case DATATYPE_ROWS:
388             {
389                 datatypeIndex++;
390
391                 // ignore the set without error
392                 if (current->getSize() != static_cast<int>(ids.size()))
393                 {
394                     return true;
395                 }
396
397                 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
398                 {
399                     std::vector<int> newDataType;
400                     controller.getObjectProperty(*it, PORT, DATATYPE, newDataType);
401
402                     double data = current->get(i);
403                     if (std::floor(data) != data)
404                     {
405                         std::string adapter = adapterName<p>(port_kind);
406                         std::string field = adapterFieldName<p>(port_kind);
407                         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s: Round number expected.\n"), adapter.data(), field.data());
408                         return false;
409                     }
410
411                     newDataType[datatypeIndex] = static_cast<int>(data);
412                     controller.setObjectProperty(*it, PORT, DATATYPE, newDataType);
413                 }
414                 return true;
415             }
416
417             case IMPLICIT:
418                 // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update
419                 return true;
420
421             default:
422                 std::string adapter = adapterName<p>(port_kind);
423                 std::string field = adapterFieldName<p>(port_kind);
424                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s .\n"), adapter.data(), field.data());
425                 return false;
426         }
427
428     }
429     else if (v->getType() == types::InternalType::ScilabBool)
430     {
431         switch (p)
432         {
433             case FIRING:
434                 // firing=%f is interpreted as "no initial event on the corresponding port", so set a negative value.
435                 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it)
436                 {
437                     controller.setObjectProperty(*it, PORT, p, -1);
438                 }
439                 return true;
440             default:
441                 std::string adapter = adapterName<p>(port_kind);
442                 std::string field = adapterFieldName<p>(port_kind);
443                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s .\n"), adapter.data(), field.data());
444                 return false;
445         }
446     }
447     std::string adapter = adapterName<p>(port_kind);
448     std::string field = adapterFieldName<p>(port_kind);
449     get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s .\n"), adapter.data(), field.data());
450     return false;
451 }
452
453 /**
454  * Fill \a newPorts with \a d values checking content if possible.
455  *
456  * \param newPorts new ports children's index or value to be filled
457  * \param children all object in the current layer (diagram or superblock)
458  * \param d the C-array values to set
459  * \return true on success, false otherwise
460  */
461 template<typename Adaptor, object_properties_t p>
462 inline bool fillNewPorts(std::deque<int>& newPorts, const std::vector<ScicosID>& children, const double* d)
463 {
464     for (std::deque<int>::iterator it = newPorts.begin(); it != newPorts.end(); ++it, ++d)
465     {
466
467         if (p == CONNECTED_SIGNALS)   // the associated link must exist
468         {
469             if (0 > *d && *d >= children.size())
470             {
471                 return false;
472             }
473             *it = static_cast<int>(*d - 1); // 'd' contains indexes
474         } // no check is performed for other properties as newPorts will contains value not index
475         else
476         {
477             *it = static_cast<int>(*d);
478         }
479     }
480     return true;
481 }
482
483 /**
484  * Set the port value
485  *
486  * \param oldPort the old port object ID
487  * \param newPort new port children's index or value
488  * \param controller current transaction instance
489  * \param children all object in the current layer (diagram or superblock)
490  * \param deletedObjects trash used to delete objects
491  */
492 template<typename Adaptor, object_properties_t p>
493 inline bool updateNewPort(const ScicosID oldPort, int newPort, Controller& controller,
494                           std::vector<ScicosID>& children, std::vector<ScicosID>& deletedObjects)
495 {
496     if (p == CONNECTED_SIGNALS)
497     {
498         // update signal and manage deconnection, using newPort as a children index
499         ScicosID oldSignal;
500         controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, oldSignal);
501
502         ScicosID newSignal;
503         if (children.size() > 0 && newPort >= 0)
504         {
505             newSignal = children[newPort];
506         }
507         else
508         {
509             newSignal = 0;
510         }
511
512         if (oldSignal != newSignal)
513         {
514             if (oldSignal == 0)
515             {
516                 // FIXME: The port was not linked, check if Link #newSignal has an unconnected end that is connectable to the port (Link kind)
517                 return false;
518             }
519             // disconnect the old link
520             ScicosID oldSignalSrc;
521             controller.getObjectProperty(oldSignal, LINK, SOURCE_PORT, oldSignalSrc);
522             ScicosID oldSignalDst;
523             controller.getObjectProperty(oldSignal, LINK, DESTINATION_PORT, oldSignalDst);
524             ScicosID unconnected = 0;
525             if (oldSignalSrc == oldPort)
526             {
527                 controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
528             }
529             else   // oldSignalDst == oldPort
530             {
531                 controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
532             }
533             // Link de-association is not performed as the link will be removed
534             // connect the new link if there is one
535             if (newSignal != 0)
536             {
537                 controller.setObjectProperty(newSignal, LINK, SOURCE_PORT, 0);
538                 controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, newSignal);
539                 children.erase(std::find(children.begin(), children.end(), oldSignal));
540                 deletedObjects.push_back(oldSignal);
541             }
542         }
543     }
544     else
545     {
546         // update the p property, using newPort as a value
547         int datatypeIndex = -1;
548         switch (p)
549         {
550             case DATATYPE_TYPE:
551                 datatypeIndex++;
552                 // no break
553             case DATATYPE_COLS:
554                 datatypeIndex++;
555                 // no break
556             case DATATYPE_ROWS:
557             {
558                 datatypeIndex++;
559                 std::vector<int> datatype;
560                 controller.getObjectProperty(oldPort, PORT, DATATYPE, datatype);
561                 datatype[datatypeIndex] = newPort;
562                 controller.setObjectProperty(oldPort, PORT, DATATYPE, datatype);
563                 return true;
564             }
565             default:
566                 controller.setObjectProperty(oldPort, PORT, p, newPort);
567         }
568     }
569     return true;
570 }
571
572 /**
573  * Add a new port
574  *
575  * \param newPortID the old port object ID
576  * \param newPort new port children's index or value
577  * \param children all object in the current layer (diagram or superblock)
578  * \param controller current transaction instance
579  * \return true on success, false otherwise
580  */
581 template<typename Adaptor, object_properties_t p>
582 inline bool addNewPort(const ScicosID newPortID, int newPort, const std::vector<ScicosID>& children, Controller& controller)
583 {
584     bool status = true;
585     if (p == CONNECTED_SIGNALS)
586     {
587         // set the connected signal if applicable, using newPort as a children index
588         if (children.size() > 0)
589         {
590             ScicosID signal = children[newPort];
591             status = controller.setObjectProperty(newPortID, PORT, CONNECTED_SIGNALS, signal) != FAIL;
592         }
593     }
594     else
595     {
596         // set the requested property, using newPort as a value
597         int datatypeIndex = -1;
598         switch (p)
599         {
600             case DATATYPE_TYPE:
601                 datatypeIndex++;
602                 // no break
603             case DATATYPE_COLS:
604                 datatypeIndex++;
605                 // no break
606             case DATATYPE_ROWS:
607             {
608                 datatypeIndex++;
609                 std::vector<int> datatype;
610                 controller.getObjectProperty(newPortID, PORT, DATATYPE, datatype);
611                 datatype[datatypeIndex] = newPort;
612                 return controller.setObjectProperty(newPortID, PORT, DATATYPE, datatype) != FAIL;
613             }
614             default:
615                 return controller.setObjectProperty(newPortID, PORT, p, newPort) != FAIL;
616         }
617     }
618
619     return status;
620 }
621
622 /**
623  * Update the ports with a specific property.
624  *
625  * Create ports if needed, remove ports if needed and set a default property on each port.
626  */
627 template<typename Adaptor, object_properties_t p>
628 bool update_ports_property(const Adaptor& adaptor, const object_properties_t port_kind, Controller& controller, types::InternalType* v)
629 {
630     ScicosID adaptee = adaptor.getAdaptee()->id();
631
632     if (v->getType() != types::InternalType::ScilabDouble)
633     {
634         std::string adapter = adapterName<p>(port_kind);
635         std::string field = adapterFieldName<p>(port_kind);
636         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), adapter.data(), field.data());
637         return false;
638     }
639     types::Double* value = v->getAs<types::Double>();
640
641     ScicosID parentBlock;
642     controller.getObjectProperty(adaptee, BLOCK, PARENT_BLOCK, parentBlock);
643     ScicosID parentDiagram;
644     controller.getObjectProperty(adaptee, BLOCK, PARENT_DIAGRAM, parentDiagram);
645
646     std::vector<ScicosID> children;
647     if (parentBlock != 0)
648     {
649         controller.getObjectProperty(parentBlock, BLOCK, CHILDREN, children);
650     }
651     if (parentDiagram != 0 && children.empty())
652     {
653         controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
654     }
655
656     std::deque<int> newPorts (value->getSize());
657
658     // retrieve old data
659     std::vector<ScicosID> previousPorts;
660     controller.getObjectProperty(adaptee, BLOCK, port_kind, previousPorts);
661     std::deque<ScicosID> oldPorts(previousPorts.begin(), previousPorts.end());
662
663     double* d = value->getReal();
664     if (!fillNewPorts<Adaptor, p>(newPorts, children, d))
665     {
666         std::string adapter = adapterName<p>(port_kind);
667         std::string field = adapterFieldName<p>(port_kind);
668         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Must be in the interval [%d, %d].\n"), adapter.data(), field.data(), 1, children.size());
669         return false;
670     }
671
672     std::vector<ScicosID> deletedObjects;
673
674     // updated ports
675     while (!oldPorts.empty() && !newPorts.empty())
676     {
677         ScicosID oldPort = oldPorts.front();
678         oldPorts.pop_front();
679         int newPort = newPorts.front();
680         newPorts.pop_front();
681
682         if (!updateNewPort<Adaptor, p>(oldPort, newPort, controller, children, deletedObjects))
683         {
684             std::string adapter = adapterName<p>(port_kind);
685             std::string field = adapterFieldName<p>(port_kind);
686             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : FIXME port has not been updated.\n"), adapter.data(), field.data(), 1, children.size());
687             return false;
688         }
689     }
690
691     // removed ports
692     if (!oldPorts.empty())
693     {
694         previousPorts.erase(previousPorts.end() - oldPorts.size(), previousPorts.end());
695
696         while (!oldPorts.empty())
697         {
698             ScicosID oldPort = oldPorts.front();
699             oldPorts.pop_front();
700
701             ScicosID signal;
702             controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, signal);
703             if (signal != 0)
704             {
705                 // the link is connected, disconnect the other side
706                 ScicosID oldSignalSrc;
707                 controller.getObjectProperty(signal, LINK, SOURCE_PORT, oldSignalSrc);
708                 ScicosID oldSignalDst;
709                 controller.getObjectProperty(signal, LINK, DESTINATION_PORT, oldSignalDst);
710
711                 ScicosID unconnected = 0;
712                 if (oldSignalSrc == oldPort)
713                 {
714                     controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
715                 }
716                 else     // oldSignalDst == oldPort
717                 {
718                     controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
719                 }
720
721                 children.erase(std::find(children.begin(), children.end(), signal));
722                 deletedObjects.push_back(signal);
723             }
724
725             deletedObjects.push_back(oldPort);
726         }
727
728         controller.setObjectProperty(adaptee, BLOCK, port_kind, previousPorts);
729     }
730
731     // added ports
732     if (!newPorts.empty())
733     {
734         while (!newPorts.empty())
735         {
736             int newPort = newPorts.front();
737             newPorts.pop_front();
738
739             ScicosID id = controller.createObject(PORT);
740             controller.setObjectProperty(id, PORT, SOURCE_BLOCK, adaptee);
741             switch (port_kind)
742             {
743                 case INPUTS:
744                     controller.setObjectProperty(id, PORT, PORT_KIND, model::PORT_IN);
745                     break;
746                 case OUTPUTS:
747                     controller.setObjectProperty(id, PORT, PORT_KIND, model::PORT_OUT);
748                     break;
749                 case EVENT_INPUTS:
750                     controller.setObjectProperty(id, PORT, PORT_KIND, model::PORT_EIN);
751                     break;
752                 case EVENT_OUTPUTS:
753                     controller.setObjectProperty(id, PORT, PORT_KIND, model::PORT_EOUT);
754                     break;
755                 default:
756                     // should never happen
757                     assert(!"Not managed kind of port");
758                     return false;
759             }
760             addNewPort<Adaptor, p>(id, newPort, children, controller);
761             previousPorts.push_back(id);
762         }
763
764         controller.setObjectProperty(adaptee, BLOCK, port_kind, previousPorts);
765     }
766
767     // remove objects from the model after de-association
768     if (parentDiagram != 0)
769     {
770         for (const ScicosID & id : children)
771         {
772             controller.referenceObject(id);
773         }
774         controller.setObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
775     }
776     for (std::vector<ScicosID>::iterator it = deletedObjects.begin(); it != deletedObjects.end(); ++it)
777     {
778         controller.deleteObject(*it);
779     }
780
781     return true;
782 }
783
784 } /* namespace view_scilab */
785 } /* namespace org_scilab_modules_scicos */
786
787 #endif /* PORTS_MANAGEMENT_HXX_ */