a6e05abad2784f757dd8cc4b620e63eeab0ed18c
[scilab.git] / scilab / modules / scicos / src / cpp / Controller.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 #include <string>
14 #include <vector>
15 #include <map>
16 #include <utility>
17 #include <algorithm>
18 #include <iterator>
19
20 #include "utilities.hxx"
21
22 #define REF_DEBUG 0
23 #if REF_DEBUG
24 #include "scilabWrite.hxx"
25 #define REF_PRINT(uid, refCount) \
26         do { \
27         std::stringstream print; \
28         print << "referenceObject( " << uid << " ) : " << refCount << std::endl; \
29         scilabForcedWrite(print.str().data()); \
30         } while(0)
31 #define UNREF_PRINT(uid, count) \
32         do { \
33         std::stringstream print; \
34         print << "unreferenceObject( " << uid << " ) : " << refCount << std::endl; \
35         scilabForcedWrite(print.str().data()); \
36         } while(0)
37 #define CLONE_PRINT(uid, clone) \
38         do { \
39         std::stringstream print; \
40         print << "cloneObject( " << uid << " ) : " << clone << std::endl; \
41         scilabForcedWrite(print.str().data()); \
42         } while(0)
43 #else
44 #define REF_PRINT(uid, refCount)
45 #define UNREF_PRINT(uid, refCount)
46 #define CLONE_PRINT(uid, clone)
47 #endif
48
49 #include "Controller.hxx"
50
51 #include "LoggerView.hxx"
52
53 namespace org_scilab_modules_scicos
54 {
55
56 /*
57  * Implement SharedData methods
58  */
59 Controller::SharedData::SharedData() :
60     model(), allNamedViews(), allViews()
61 {
62 }
63
64 Controller::SharedData::~SharedData()
65 {
66     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
67     {
68         delete *iter;
69     }
70 }
71
72 Controller::SharedData Controller::m_instance;
73
74 View* Controller::register_view(const std::string& name, View* v)
75 {
76     m_instance.allNamedViews.push_back(name);
77     m_instance.allViews.push_back(v);
78     return v;
79 }
80
81 void Controller::unregister_view(View* v)
82 {
83     view_set_t::iterator it = std::find(m_instance.allViews.begin(), m_instance.allViews.end(), v);
84     if (it != m_instance.allViews.end())
85     {
86         size_t d = std::distance(m_instance.allViews.begin(), it);
87         m_instance.allNamedViews.erase(m_instance.allNamedViews.begin() + d);
88         m_instance.allViews.erase(m_instance.allViews.begin() + d);
89     }
90 }
91
92 View* Controller::unregister_view(const std::string& name)
93 {
94     View* view = nullptr;
95
96     view_name_set_t::iterator it = std::find(m_instance.allNamedViews.begin(), m_instance.allNamedViews.end(), name);
97     if (it != m_instance.allNamedViews.end())
98     {
99         size_t d = std::distance(m_instance.allNamedViews.begin(), it);
100         view = *(m_instance.allViews.begin() + d);
101         m_instance.allNamedViews.erase(m_instance.allNamedViews.begin() + d);
102         m_instance.allViews.erase(m_instance.allViews.begin() + d);
103     }
104
105     return view;
106 }
107
108 View* Controller::look_for_view(const std::string& name)
109 {
110     View* view = nullptr;
111
112     view_name_set_t::iterator it = std::find(m_instance.allNamedViews.begin(), m_instance.allNamedViews.end(), name);
113     if (it != m_instance.allNamedViews.end())
114     {
115         size_t d = std::distance(m_instance.allNamedViews.begin(), it);
116         view = *(m_instance.allViews.begin() + d);
117     }
118
119     return view;
120 }
121
122 Controller::Controller()
123 {
124 }
125
126 Controller::~Controller()
127 {
128 }
129
130 ScicosID Controller::createObject(kind_t k)
131 {
132     ScicosID uid = m_instance.model.createObject(k);
133
134     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
135     {
136         (*iter)->objectCreated(uid, k);
137     }
138
139     return uid;
140 }
141
142 unsigned Controller::referenceObject(const ScicosID uid) const
143 {
144     unsigned refCount = m_instance.model.referenceObject(uid);
145     REF_PRINT(uid, refCount);
146
147     auto o = getObject(uid);
148     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
149     {
150         (*iter)->objectReferenced(uid, o->kind(), refCount);
151     }
152
153     return refCount;
154 }
155
156 void Controller::deleteObject(ScicosID uid)
157 {
158     // if this object is the empty uid, ignore it : is is not stored in the model
159     if (uid == 0)
160     {
161         return;
162     }
163
164     auto initial = getObject(uid);
165     if (initial == nullptr)
166     {
167         // defensive programming
168         return;
169     }
170     const kind_t k = initial->kind();
171
172     // if this object has been referenced somewhere else do not delete it but decrement the reference counter
173     unsigned& refCount = m_instance.model.referenceCount(uid);
174     if (refCount > 0)
175     {
176         --refCount;
177         UNREF_PRINT(uid, refCount);
178
179         for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
180         {
181             (*iter)->objectUnreferenced(uid, k, refCount);
182         }
183         return;
184     }
185
186     // We need to delete this object and cleanup all the referenced model object
187
188     // disconnect / remove references of weak connected objects and decrement the reference count of all strongly connected objects.
189     if (k == ANNOTATION)
190     {
191         unlinkVector(uid, k, PARENT_DIAGRAM, CHILDREN);
192         unlinkVector(uid, k, PARENT_BLOCK, CHILDREN);
193         // RELATED_TO is not referenced back
194     }
195     else if (k == BLOCK)
196     {
197         unlinkVector(uid, k, PARENT_DIAGRAM, CHILDREN);
198         unlinkVector(uid, k, PARENT_BLOCK, CHILDREN);
199
200         deleteVector(uid, k, INPUTS);
201         deleteVector(uid, k, OUTPUTS);
202         deleteVector(uid, k, EVENT_INPUTS);
203         deleteVector(uid, k, EVENT_OUTPUTS);
204
205         unlink(uid, k, CHILDREN, PARENT_BLOCK);
206         deleteVector(uid, k, CHILDREN);
207         // FIXME what about REFERENCED_PORT ?
208     }
209     else if (k == DIAGRAM)
210     {
211         unlink(uid, k, CHILDREN, PARENT_DIAGRAM);
212         deleteVector(uid, k, CHILDREN);
213     }
214     else if (k == LINK)
215     {
216         unlinkVector(uid, k, PARENT_DIAGRAM, CHILDREN);
217         unlinkVector(uid, k, PARENT_BLOCK, CHILDREN);
218
219         unlinkVector(uid, k, SOURCE_PORT, CONNECTED_SIGNALS);
220         unlinkVector(uid, k, DESTINATION_PORT, CONNECTED_SIGNALS);
221     }
222     else if (k == PORT)
223     {
224         unlinkVector(uid, k, SOURCE_BLOCK, INPUTS);
225         unlinkVector(uid, k, SOURCE_BLOCK, OUTPUTS);
226         unlinkVector(uid, k, SOURCE_BLOCK, EVENT_INPUTS);
227         unlinkVector(uid, k, SOURCE_BLOCK, EVENT_OUTPUTS);
228
229         unlink(uid, k, CONNECTED_SIGNALS, SOURCE_PORT);
230         unlink(uid, k, CONNECTED_SIGNALS, DESTINATION_PORT);
231     }
232
233     // delete the object
234     m_instance.model.deleteObject(uid);
235
236     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
237     {
238         (*iter)->objectDeleted(uid, k);
239     }
240 }
241
242 void Controller::unlinkVector(ScicosID uid, kind_t k, object_properties_t uid_prop, object_properties_t ref_prop)
243 {
244     ScicosID v;
245     getObjectProperty(uid, k, uid_prop, v);
246     if (v != 0)
247     {
248         auto o = getObject(v);
249         if (o == nullptr)
250         {
251             return;
252         }
253
254         std::vector<ScicosID> children;
255         getObjectProperty(o->id(), o->kind(), ref_prop, children);
256
257         std::vector<ScicosID>::iterator it = std::find(children.begin(), children.end(), uid);
258         if (it != children.end())
259         {
260             children.erase(it);
261         }
262
263         setObjectProperty(o->id(), o->kind(), ref_prop, children);
264     }
265 }
266
267 void Controller::unlink(ScicosID uid, kind_t k, object_properties_t uid_prop, object_properties_t ref_prop)
268 {
269     std::vector<ScicosID> v;
270     getObjectProperty(uid, k, uid_prop, v);
271     for (const ScicosID id : v)
272     {
273         if (id != 0)
274         {
275             auto o = getObject(id);
276             if (o == nullptr)
277             {
278                 continue;
279             }
280
281             // Find which end of the link is connected to the port
282             ScicosID oppositeRef;
283             getObjectProperty(o->id(), o->kind(), ref_prop, oppositeRef);
284             if (oppositeRef == uid)
285             {
286                 setObjectProperty(o->id(), o->kind(), ref_prop, ScicosID());
287             }
288         }
289     }
290 }
291
292 void Controller::deleteVector(ScicosID uid, kind_t k, object_properties_t uid_prop)
293 {
294     std::vector<ScicosID> children;
295     getObjectProperty(uid, k, uid_prop, children);
296
297     for (ScicosID id : children)
298     {
299         deleteObject(id);
300     }
301 }
302
303 ScicosID Controller::cloneObject(std::map<ScicosID, ScicosID>& mapped, ScicosID uid, bool cloneChildren)
304 {
305     auto initial = getObject(uid);
306     const kind_t k = initial->kind();
307     ScicosID o = createObject(k);
308     mapped.insert(std::make_pair(uid, o));
309
310     // Get then set all properties per type that do not manage ScicosID
311     cloneProperties<double>(initial, o);
312     cloneProperties<int>(initial, o);
313     cloneProperties<bool>(initial, o);
314     cloneProperties<std::string>(initial, o);
315     cloneProperties<std::vector<double> >(initial, o);
316     cloneProperties<std::vector<int> >(initial, o);
317     cloneProperties<std::vector<std::string> >(initial, o);
318
319     // deep copy children, manage ScicosID and std::vector<ScicosID>
320     if (k == ANNOTATION)
321     {
322         deepClone(mapped, uid, o, k, PARENT_DIAGRAM, false);
323         deepClone(mapped, uid, o, k, PARENT_BLOCK, false);
324         deepClone(mapped, uid, o, k, RELATED_TO, true);
325     }
326     else if (k == BLOCK)
327     {
328         deepClone(mapped, uid, o, k, PARENT_DIAGRAM, false);
329         deepCloneVector(mapped, uid, o, k, INPUTS, true);
330         deepCloneVector(mapped, uid, o, k, OUTPUTS, true);
331         deepCloneVector(mapped, uid, o, k, EVENT_INPUTS, true);
332         deepCloneVector(mapped, uid, o, k, EVENT_OUTPUTS, true);
333
334         deepClone(mapped, uid, o, k, PARENT_BLOCK, false);
335         if (cloneChildren)
336         {
337             deepCloneVector(mapped, uid, o, k, CHILDREN, true);
338         }
339         // FIXME what about REFERENCED_PORT ?
340     }
341     else if (k == DIAGRAM)
342     {
343         if (cloneChildren)
344         {
345             deepCloneVector(mapped, uid, o, k, CHILDREN, true);
346         }
347     }
348     else if (k == LINK)
349     {
350         deepClone(mapped, uid, o, k, PARENT_DIAGRAM, false);
351         deepClone(mapped, uid, o, k, PARENT_BLOCK, false);
352         deepClone(mapped, uid, o, k, SOURCE_PORT, false);
353         deepClone(mapped, uid, o, k, DESTINATION_PORT, false);
354     }
355     else if (k == PORT)
356     {
357         deepClone(mapped, uid, o, k, SOURCE_BLOCK, false);
358         deepCloneVector(mapped, uid, o, k, CONNECTED_SIGNALS, false);
359     }
360
361     return o;
362 }
363
364 void Controller::deepClone(std::map<ScicosID, ScicosID>& mapped, ScicosID uid, ScicosID clone, kind_t k, object_properties_t p, bool cloneIfNotFound)
365 {
366     ScicosID v;
367     getObjectProperty(uid, k, p, v);
368
369     ScicosID cloned = 0;
370
371     std::map<ScicosID, ScicosID>::iterator it = mapped.find(v);
372     if (it != mapped.end())
373     {
374         cloned = it->second;
375     }
376     else
377     {
378         if (cloneIfNotFound)
379         {
380             if (v != 0)
381             {
382                 cloned = cloneObject(mapped, v, true);
383             }
384             else
385             {
386                 cloned = 0;
387             }
388         }
389         else
390         {
391             cloned = 0;
392         }
393     }
394
395     setObjectProperty(clone, k, p, cloned);
396 }
397
398 void Controller::deepCloneVector(std::map<ScicosID, ScicosID>& mapped, ScicosID uid, ScicosID clone, kind_t k, object_properties_t p, bool cloneIfNotFound)
399 {
400     std::vector<ScicosID> v;
401     getObjectProperty(uid, k, p, v);
402
403     std::vector<ScicosID> cloned;
404     cloned.reserve(v.size());
405
406     for (const ScicosID & id : v)
407     {
408         if (id == 0)
409         {
410             // Deleted Block, the cloning is done at Adapter level
411             cloned.push_back(id);
412             continue;
413         }
414
415         std::map<ScicosID, ScicosID>::iterator it = mapped.find(id);
416         if (it != mapped.end())
417         {
418             cloned.push_back(it->second);
419         }
420         else
421         {
422             if (cloneIfNotFound)
423             {
424                 if (id != 0)
425                 {
426                     cloned.push_back(cloneObject(mapped, id, true));
427                 }
428                 else
429                 {
430                     cloned.push_back(ScicosID());
431                 }
432             }
433             else
434             {
435                 cloned.push_back(ScicosID());
436             }
437         }
438     }
439
440     setObjectProperty(clone, k, p, cloned);
441 }
442
443 ScicosID Controller::cloneObject(ScicosID uid, bool cloneChildren)
444 {
445     std::map<ScicosID, ScicosID> mapped;
446     ScicosID clone = cloneObject(mapped, uid, cloneChildren);
447     CLONE_PRINT(uid, clone);
448     return clone;
449 }
450
451 kind_t Controller::getKind(ScicosID uid) const
452 {
453     return m_instance.model.getKind(uid);
454 }
455
456 std::vector<ScicosID> Controller::getAll(kind_t k) const
457 {
458     return m_instance.model.getAll(k);
459 }
460
461 model::BaseObject* Controller::getObject(ScicosID uid) const
462 {
463     return m_instance.model.getObject(uid);
464 }
465
466 } /* namespace org_scilab_modules_scicos */