source: finroc_plugins_composite_ports/auto_connect.cpp @ 28:0d9e9fd957de

tip
Last change on this file since 28:0d9e9fd957de was 12:35b3eecd8d06, checked in by Max Reichardt <max.reichardt@…>, 22 months ago

Adds parameter to ConnectUnconnectedMatchingInterfaces convenience function

File size: 7.7 KB
Line 
1//
2// You received this file as part of Finroc
3// A framework for intelligent robot control
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    plugins/composite_ports/auto_connect.cpp
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2020-02-18
27 *
28 */
29//----------------------------------------------------------------------
30#include "plugins/composite_ports/auto_connect.h"
31
32//----------------------------------------------------------------------
33// External includes (system with <>, local with "")
34//----------------------------------------------------------------------
35#include "rrlib/rtti_conversion/tStaticCastOperation.h"
36
37//----------------------------------------------------------------------
38// Internal includes with ""
39//----------------------------------------------------------------------
40
41//----------------------------------------------------------------------
42// Debugging
43//----------------------------------------------------------------------
44#include <cassert>
45
46//----------------------------------------------------------------------
47// Namespace usage
48//----------------------------------------------------------------------
49
50//----------------------------------------------------------------------
51// Namespace declaration
52//----------------------------------------------------------------------
53namespace finroc
54{
55namespace composite_ports
56{
57
58//----------------------------------------------------------------------
59// Forward declarations / typedefs / enums
60//----------------------------------------------------------------------
61
62typedef core::tFrameworkElementFlag tFlag;
63typedef tInterfaceBase::tBackend tBackend;
64
65//----------------------------------------------------------------------
66// Const values
67//----------------------------------------------------------------------
68
69//----------------------------------------------------------------------
70// Implementation
71//----------------------------------------------------------------------
72
73namespace
74{
75
76bool IsConnectedToComponent(core::tFrameworkElement& component, tInterfaceBase::tBackend& primary_backend)
77{
78  for (auto it = primary_backend.IncomingConnectionsBegin(); it != primary_backend.IncomingConnectionsEnd(); ++it)
79  {
80    auto aggregator = core::tEdgeAggregator::GetAggregator(it->Source());
81    if (aggregator && aggregator->GetParent() == &component)
82    {
83      return true;
84    }
85  }
86  for (auto it = primary_backend.OutgoingConnectionsBegin(); it != primary_backend.OutgoingConnectionsEnd(); ++it)
87  {
88    auto aggregator = core::tEdgeAggregator::GetAggregator(it->Destination());
89    if (aggregator && aggregator->GetParent() == &component)
90    {
91      return true;
92    }
93  }
94  return false;
95}
96
97bool ConnectUnconnectedMatchingInterface(core::tFrameworkElement& source_parent, core::tPortGroup& destination_component_interface, core::tAbstractPort& destination_port, bool connect_derived_interfaces, bool connect_to_nested_source_interfaces)
98{
99  std::vector<core::tAbstractPort*> unconnected_source_interface_ports;
100  for (auto source_port = source_parent.ChildPortsBegin(); source_port != source_parent.ChildPortsEnd(); ++source_port)
101  {
102    bool already_connected = false;
103    for (auto connector = source_port->OutgoingConnectionsBegin(); connector != source_port->OutgoingConnectionsEnd(); ++connector)
104    {
105      auto aggregator = core::tEdgeAggregator::GetAggregator(connector->Destination());
106      if (aggregator == &destination_component_interface)
107      {
108        already_connected = true;
109        break;
110      }
111    }
112
113    if (!already_connected)
114    {
115      if (source_port->IsReady() && source_port->GetDataType().GetTypeClassification() == rrlib::rtti::tTypeClassification::PORT_COMPOSITE_INTERFACE && (source_port->GetDataType() == destination_port.GetDataType() || (connect_derived_interfaces && rrlib::rtti::conversion::tStaticCastOperation::IsImplicitlyConvertibleTo(source_port->GetDataType(), destination_port.GetDataType()))))
116      {
117        source_port->ConnectTo(destination_port);
118        return true;
119      }
120      else if (connect_to_nested_source_interfaces)
121      {
122        unconnected_source_interface_ports.push_back(&*source_port);
123      }
124    }
125  }
126
127  // still not connected
128  assert(destination_port.CountIncomingConnections() == 0);
129  for (auto & source_port : unconnected_source_interface_ports)
130  {
131    if (ConnectUnconnectedMatchingInterface(*source_port, destination_component_interface, destination_port, connect_derived_interfaces, connect_to_nested_source_interfaces))
132    {
133      return true;
134    }
135  }
136  return false;
137}
138
139}
140
141namespace internal
142{
143
144std::vector<tInterfaceBase> GetChildComponentInterfaces(core::tFrameworkElement& composite_component, const rrlib::rtti::tType& interface_type, bool unconnected_only)
145{
146  std::vector<tInterfaceBase> result;
147  if (!interface_type)
148  {
149    // -> no interfaces of this type exist
150    return result;
151  }
152
153  for (auto component_element = composite_component.ChildrenBegin(); component_element != composite_component.ChildrenEnd(); ++component_element)
154  {
155    if (IsComponent(&*component_element))
156    {
157      core::tFrameworkElement& component = *component_element;
158      for (auto component_interface = component.ChildrenBegin(); component_interface != component.ChildrenEnd(); ++component_interface)
159      {
160        if (component_interface->GetFlag(tFlag::EDGE_AGGREGATOR))
161        {
162          for (auto element_in_interface = component_interface->ChildrenBegin(); element_in_interface != component_interface->ChildrenEnd(); ++element_in_interface)
163          {
164            if (tInterfaceBase::IsInterface(*element_in_interface))
165            {
166              tBackend& backend = static_cast<tBackend&>(*element_in_interface);
167              if (backend.AllBackends().front() == &backend && backend.GetDataType() == interface_type && ((!unconnected_only) || (!IsConnectedToComponent(composite_component, backend)))) // only return primary interfaces
168              {
169                result.emplace_back(&backend);
170              }
171            }
172          }
173        }
174      }
175    }
176  }
177  return result;
178}
179
180}
181
182void ConnectUnconnectedMatchingInterfaces(core::tPortGroup& source_component_interface, core::tPortGroup& destination_component_interface, bool connect_derived_interfaces, bool connect_to_nested_source_interfaces)
183{
184  for (auto destination_port = destination_component_interface.ChildPortsBegin(); destination_port != destination_component_interface.ChildPortsEnd(); ++destination_port)
185  {
186    if (destination_port->IsReady() && destination_port->GetDataType().GetTypeClassification() == rrlib::rtti::tTypeClassification::PORT_COMPOSITE_INTERFACE && destination_port->CountIncomingConnections() == 0)
187    {
188      ConnectUnconnectedMatchingInterface(source_component_interface, destination_component_interface, *destination_port, connect_derived_interfaces, connect_to_nested_source_interfaces);
189    }
190  }
191}
192
193
194//----------------------------------------------------------------------
195// End of namespace declaration
196//----------------------------------------------------------------------
197}
198}
Note: See TracBrowser for help on using the repository browser.