2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014-2016 - Scilab Enterprises - Clement DAVID
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
24 #include "utilities.hxx"
26 #include "Controller.hxx"
27 #include "model/BaseObject.hxx"
29 #include "LoggerView.hxx"
35 namespace org_scilab_modules_scicos
39 * Implement SharedData methods
41 Controller::SharedData::SharedData() :
42 onModelStructuralModification(), model(),
43 onViewsStructuralModification(), allNamedViews(), allViews()
45 unlock(&onModelStructuralModification);
46 unlock(&onViewsStructuralModification);
49 Controller::SharedData::~SharedData()
51 lock(&onViewsStructuralModification);
52 for (view_set_t::iterator iter = allViews.begin(); iter != allViews.end(); ++iter)
56 unlock(&onViewsStructuralModification);
59 Controller::SharedData Controller::m_instance;
61 View* Controller::register_view(const std::string& name, View* v)
63 lock(&m_instance.onViewsStructuralModification);
65 m_instance.allNamedViews.push_back(name);
66 m_instance.allViews.push_back(v);
68 unlock(&m_instance.onViewsStructuralModification);
72 void Controller::unregister_view(View* v)
74 lock(&m_instance.onViewsStructuralModification);
76 view_set_t::iterator it = std::find(m_instance.allViews.begin(), m_instance.allViews.end(), v);
77 if (it != m_instance.allViews.end())
79 size_t d = std::distance(m_instance.allViews.begin(), it);
80 m_instance.allNamedViews.erase(m_instance.allNamedViews.begin() + d);
81 m_instance.allViews.erase(m_instance.allViews.begin() + d);
84 unlock(&m_instance.onViewsStructuralModification);
87 View* Controller::unregister_view(const std::string& name)
91 lock(&m_instance.onViewsStructuralModification);
93 view_name_set_t::iterator it = std::find(m_instance.allNamedViews.begin(), m_instance.allNamedViews.end(), name);
94 if (it != m_instance.allNamedViews.end())
96 size_t d = std::distance(m_instance.allNamedViews.begin(), it);
97 view = *(m_instance.allViews.begin() + d);
98 m_instance.allNamedViews.erase(m_instance.allNamedViews.begin() + d);
99 m_instance.allViews.erase(m_instance.allViews.begin() + d);
101 unlock(&m_instance.onViewsStructuralModification);
106 View* Controller::look_for_view(const std::string& name)
108 View* view = nullptr;
110 lock(&m_instance.onViewsStructuralModification);
111 view_name_set_t::iterator it = std::find(m_instance.allNamedViews.begin(), m_instance.allNamedViews.end(), name);
112 if (it != m_instance.allNamedViews.end())
114 size_t d = std::distance(m_instance.allNamedViews.begin(), it);
115 view = *(m_instance.allViews.begin() + d);
117 unlock(&m_instance.onViewsStructuralModification);
122 void Controller::end_simulation()
127 Controller::Controller()
131 Controller::~Controller()
135 ScicosID Controller::createObject(kind_t k)
137 lock(&m_instance.onModelStructuralModification);
138 ScicosID uid = m_instance.model.createObject(k);
139 unlock(&m_instance.onModelStructuralModification);
141 lock(&m_instance.onViewsStructuralModification);
142 for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
144 (*iter)->objectCreated(uid, k);
146 unlock(&m_instance.onViewsStructuralModification);
151 unsigned Controller::referenceObject(const ScicosID uid) const
153 lock(&m_instance.onModelStructuralModification);
155 unsigned refCount = m_instance.model.referenceObject(uid);
157 auto o = m_instance.model.getObject(uid);
158 unlock(&m_instance.onModelStructuralModification);
161 // defensive programming
165 lock(&m_instance.onViewsStructuralModification);
166 for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
168 (*iter)->objectReferenced(uid, o->kind(), refCount);
170 unlock(&m_instance.onViewsStructuralModification);
175 void Controller::deleteObject(ScicosID uid)
177 // if this object is the empty uid, ignore it : is is not stored in the model
178 if (uid == ScicosID())
183 lock(&m_instance.onModelStructuralModification);
185 auto initial = m_instance.model.getObject(uid);
186 if (initial == nullptr)
188 // defensive programming
189 unlock(&m_instance.onModelStructuralModification);
192 const kind_t k = initial->kind();
194 // if this object has been referenced somewhere else do not delete it but decrement the reference counter
195 unsigned& refCount = m_instance.model.referenceCount(uid);
196 unlock(&m_instance.onModelStructuralModification);
201 lock(&m_instance.onViewsStructuralModification);
202 for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
204 (*iter)->objectUnreferenced(uid, k, refCount);
206 unlock(&m_instance.onViewsStructuralModification);
210 // We need to delete this object and cleanup all the referenced model object
212 // disconnect / remove references of weak connected objects and decrement the reference count of all strongly connected objects.
215 unlinkVector(initial, PARENT_DIAGRAM, CHILDREN);
216 unlinkVector(initial, PARENT_BLOCK, CHILDREN);
217 // RELATED_TO is not referenced back
221 unlinkVector(initial, PARENT_DIAGRAM, CHILDREN);
222 unlinkVector(initial, PARENT_BLOCK, CHILDREN);
224 deleteVector(initial, INPUTS);
225 deleteVector(initial, OUTPUTS);
226 deleteVector(initial, EVENT_INPUTS);
227 deleteVector(initial, EVENT_OUTPUTS);
229 unlink(initial, CHILDREN, PARENT_BLOCK);
230 deleteVector(initial, CHILDREN);
231 // FIXME what about REFERENCED_PORT ?
233 else if (k == DIAGRAM)
235 unlink(initial, CHILDREN, PARENT_DIAGRAM);
236 deleteVector(initial, CHILDREN);
240 unlinkVector(initial, PARENT_DIAGRAM, CHILDREN);
241 unlinkVector(initial, PARENT_BLOCK, CHILDREN);
243 unlinkVector(initial, SOURCE_PORT, CONNECTED_SIGNALS);
244 unlinkVector(initial, DESTINATION_PORT, CONNECTED_SIGNALS);
248 unlinkVector(initial, SOURCE_BLOCK, INPUTS);
249 unlinkVector(initial, SOURCE_BLOCK, OUTPUTS);
250 unlinkVector(initial, SOURCE_BLOCK, EVENT_INPUTS);
251 unlinkVector(initial, SOURCE_BLOCK, EVENT_OUTPUTS);
253 unlink(initial, CONNECTED_SIGNALS, SOURCE_PORT);
254 unlink(initial, CONNECTED_SIGNALS, DESTINATION_PORT);
258 lock(&m_instance.onModelStructuralModification);
259 m_instance.model.deleteObject(uid);
260 unlock(&m_instance.onModelStructuralModification);
262 lock(&m_instance.onViewsStructuralModification);
263 for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
265 (*iter)->objectDeleted(uid, k);
267 unlock(&m_instance.onViewsStructuralModification);
270 void Controller::unlinkVector(model::BaseObject* initial, object_properties_t uid_prop, object_properties_t ref_prop)
273 getObjectProperty(initial->id(), initial->kind(), uid_prop, v);
276 auto o = getObject(v);
282 std::vector<ScicosID> children;
283 getObjectProperty(o->id(), o->kind(), ref_prop, children);
285 std::vector<ScicosID>::iterator it = std::find(children.begin(), children.end(), initial->id());
286 if (it != children.end())
291 setObjectProperty(o->id(), o->kind(), ref_prop, children);
295 void Controller::unlink(model::BaseObject* initial, object_properties_t uid_prop, object_properties_t ref_prop)
297 std::vector<ScicosID> v;
298 getObjectProperty(initial->id(), initial->kind(), uid_prop, v);
299 for (const ScicosID id : v)
301 if (id != ScicosID())
303 auto o = getObject(id);
309 // Find which end of the link is connected to the port
310 ScicosID oppositeRef;
311 getObjectProperty(o->id(), o->kind(), ref_prop, oppositeRef);
312 if (oppositeRef == initial->id())
314 setObjectProperty(o->id(), o->kind(), ref_prop, ScicosID());
320 void Controller::deleteVector(model::BaseObject* initial, object_properties_t uid_prop)
322 std::vector<ScicosID> children;
323 getObjectProperty(initial->id(), initial->kind(), uid_prop, children);
325 for (ScicosID id : children)
332 void Controller::cloneProperties(model::BaseObject* initial, model::BaseObject* clone)
334 for (int i = 0; i < MAX_OBJECT_PROPERTIES; ++i)
336 enum object_properties_t p = static_cast<enum object_properties_t>(i);
339 bool status = getObjectProperty(initial, p, value);
342 setObjectProperty(clone, p, value);
347 model::BaseObject* Controller::cloneObject(std::map<model::BaseObject*, model::BaseObject*>& mapped, model::BaseObject* initial, bool cloneChildren, bool clonePorts)
349 const kind_t k = initial->kind();
350 ScicosID o = createObject(k);
351 model::BaseObject* cloned = getObject(o);
352 mapped.insert(std::make_pair(initial, cloned));
354 lock(&m_instance.onViewsStructuralModification);
355 for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
357 (*iter)->objectCloned(initial->id(), o, k);
359 unlock(&m_instance.onViewsStructuralModification);
361 // Get then set all properties per type that do not manage ScicosID
362 cloneProperties<double>(initial, cloned);
363 cloneProperties<int>(initial, cloned);
364 cloneProperties<bool>(initial, cloned);
365 cloneProperties<std::string>(initial, cloned);
366 cloneProperties<std::vector<double> >(initial, cloned);
367 cloneProperties<std::vector<int> >(initial, cloned);
368 cloneProperties<std::vector<std::string> >(initial, cloned);
370 // deep copy children, manage ScicosID and std::vector<ScicosID>
373 deepClone(mapped, initial, cloned, PARENT_DIAGRAM, false);
374 deepClone(mapped, initial, cloned, PARENT_BLOCK, false);
375 deepClone(mapped, initial, cloned, RELATED_TO, true);
379 deepClone(mapped, initial, cloned, PARENT_DIAGRAM, false);
382 // copy the block and all its ports
383 deepCloneVector(mapped, initial, cloned, INPUTS, true);
384 deepCloneVector(mapped, initial, cloned, OUTPUTS, true);
385 deepCloneVector(mapped, initial, cloned, EVENT_INPUTS, true);
386 deepCloneVector(mapped, initial, cloned, EVENT_OUTPUTS, true);
389 deepClone(mapped, initial, cloned, PARENT_BLOCK, false);
392 deepCloneVector(mapped, initial, cloned, CHILDREN, true);
394 // FIXME what about REFERENCED_PORT ?
396 else if (k == DIAGRAM)
400 deepCloneVector(mapped, initial, cloned, CHILDREN, true);
405 deepClone(mapped, initial, cloned, PARENT_DIAGRAM, false);
406 deepClone(mapped, initial, cloned, PARENT_BLOCK, false);
407 deepClone(mapped, initial, cloned, SOURCE_PORT, false);
408 deepClone(mapped, initial, cloned, DESTINATION_PORT, false);
412 deepClone(mapped, initial, cloned, SOURCE_BLOCK, false);
413 deepCloneVector(mapped, initial, cloned, CONNECTED_SIGNALS, false);
418 void Controller::deepClone(std::map<model::BaseObject*, model::BaseObject*>& mapped, model::BaseObject* initial, model::BaseObject* clone, object_properties_t p, bool cloneIfNotFound)
421 getObjectProperty(initial, p, v);
423 model::BaseObject* opposite = getObject(v);
424 model::BaseObject* cloned;
426 std::map<model::BaseObject*, model::BaseObject*>::iterator it = mapped.find(opposite);
427 if (it != mapped.end())
437 cloned = cloneObject(mapped, opposite, true, true);
450 if (cloned == nullptr)
452 setObjectProperty(clone, p, ScicosID());
456 setObjectProperty(clone, p, cloned->id());
460 void Controller::deepCloneVector(std::map<model::BaseObject*, model::BaseObject*>& mapped, model::BaseObject* initial, model::BaseObject* clone, object_properties_t p, bool cloneIfNotFound)
462 std::vector<ScicosID> v;
463 getObjectProperty(initial, p, v);
465 std::vector<model::BaseObject*> cloned;
466 cloned.reserve(v.size());
468 for (const ScicosID & id : v)
470 if (id == ScicosID())
472 // Deleted Block, the cloning is done at Adapter level
473 cloned.push_back(nullptr);
477 model::BaseObject* opposite = getObject(id);
478 std::map<model::BaseObject*, model::BaseObject*>::iterator it = mapped.find(opposite);
479 if (it != mapped.end())
481 cloned.push_back(it->second);
487 if (id != ScicosID())
489 model::BaseObject* clone = cloneObject(mapped, opposite, true, true);
490 cloned.push_back(clone);
494 cloned.push_back(nullptr);
499 cloned.push_back(getObject(id));
504 // update the ScicosID related properties after cloning all the objects
507 for (auto const& it : mapped)
509 model::BaseObject* initial = it.first;
510 model::BaseObject* cloned = it.second;
512 switch (initial->kind())
515 deepCloneVector(mapped, initial, cloned, CONNECTED_SIGNALS, false);
518 deepClone(mapped, initial, cloned, SOURCE_PORT, false);
519 deepClone(mapped, initial, cloned, DESTINATION_PORT, false);
527 // set the main object vector property
528 std::vector<ScicosID> clonedUIDs(cloned.size());
529 std::transform(cloned.begin(), cloned.end(), clonedUIDs.begin(), [](model::BaseObject * o)
541 setObjectProperty(clone, p, clonedUIDs);
544 ScicosID Controller::cloneObject(ScicosID uid, bool cloneChildren, bool clonePorts)
546 std::map<model::BaseObject*, model::BaseObject*> mapped;
547 model::BaseObject* clone = cloneObject(mapped, getObject(uid), cloneChildren, clonePorts);
552 kind_t Controller::getKind(ScicosID uid) const
554 lock(&m_instance.onModelStructuralModification);
556 kind_t kind = m_instance.model.getKind(uid);
558 unlock(&m_instance.onModelStructuralModification);
562 std::vector<ScicosID> Controller::getAll(kind_t k) const
564 lock(&m_instance.onModelStructuralModification);
566 auto vec = m_instance.model.getAll(k);
568 unlock(&m_instance.onModelStructuralModification);
572 void Controller::sortAndFillKind(std::vector<ScicosID>& uids, std::vector<int>& kinds)
574 lock(&m_instance.onModelStructuralModification);
576 // create a container of pair
582 std::vector<local_pair> container(uids.size());
585 for (size_t i = 0; i < uids.size(); ++i)
587 container[i] = { uids[i], m_instance.model.getKind(uids[i]) };
590 // sort according to the kinds
591 std::stable_sort(container.begin(), container.end(), [] (const local_pair & a, const local_pair & b)
593 return a.second < b.second;
598 kinds.reserve(uids.capacity());
599 for (const auto & v : container)
601 uids.push_back(v.first);
602 kinds.push_back(v.second);
605 unlock(&m_instance.onModelStructuralModification);
609 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, T& v) const
611 lock(&m_instance.onModelStructuralModification);
612 bool ret = m_instance.model.getObjectProperty(uid, k, p, v);
613 unlock(&m_instance.onModelStructuralModification);
617 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, double& v) const
619 return getObjectProperty<>(uid, k, p, v);
621 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, int& v) const
623 return getObjectProperty<>(uid, k, p, v);
625 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, bool& v) const
627 return getObjectProperty<>(uid, k, p, v);
629 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::string& v) const
631 return getObjectProperty<>(uid, k, p, v);
633 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, ScicosID& v) const
635 return getObjectProperty<>(uid, k, p, v);
637 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<double>& v) const
639 return getObjectProperty<>(uid, k, p, v);
641 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<int>& v) const
643 return getObjectProperty<>(uid, k, p, v);
645 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<bool>& v) const
647 return getObjectProperty<>(uid, k, p, v);
649 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector< std::string >& v) const
651 return getObjectProperty<>(uid, k, p, v);
653 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<ScicosID>& v) const
655 return getObjectProperty<>(uid, k, p, v);
659 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, T v)
661 lock(&m_instance.onModelStructuralModification);
662 update_status_t status = m_instance.model.setObjectProperty(uid, k, p, v);
663 unlock(&m_instance.onModelStructuralModification);
665 lock(&m_instance.onViewsStructuralModification);
666 for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
668 (*iter)->propertyUpdated(uid, k, p, status);
670 unlock(&m_instance.onViewsStructuralModification);
674 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, double v)
676 return setObjectProperty<>(uid, k, p, v);
678 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, int v)
680 return setObjectProperty<>(uid, k, p, v);
682 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, bool v)
684 return setObjectProperty<>(uid, k, p, v);
686 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, ScicosID v)
688 return setObjectProperty<>(uid, k, p, v);
690 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::string& v)
692 return setObjectProperty<>(uid, k, p, v);
694 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<double>& v)
696 return setObjectProperty<>(uid, k, p, v);
698 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<int>& v)
700 return setObjectProperty<>(uid, k, p, v);
702 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<bool>& v)
704 return setObjectProperty<>(uid, k, p, v);
706 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector< std::string >& v)
708 return setObjectProperty<>(uid, k, p, v);
710 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<ScicosID>& v)
712 return setObjectProperty<>(uid, k, p, v);
715 model::BaseObject* Controller::getObject(ScicosID uid) const
717 lock(&m_instance.onModelStructuralModification);
718 model::BaseObject* o = m_instance.model.getObject(uid);
719 unlock(&m_instance.onModelStructuralModification);
723 } /* namespace org_scilab_modules_scicos */