selxSuperElastixComponent.hxx 7.67 KB
Newer Older
Floris Berendsen's avatar
Floris Berendsen committed
1
2
/*=========================================================================
 *
3
 *  Copyright Leiden University Medical Center, Erasmus University Medical
Floris Berendsen's avatar
Floris Berendsen committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *  Center and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

20
21
#ifndef selxSuperElastixComponent_hxx
#define selxSuperElastixComponent_hxx
22

23
#include "selxInterfaceTraits.h"
Floris Berendsen's avatar
Floris Berendsen committed
24
namespace selx
25
{
26
27
28
29
30
31
template< class InterfaceT >
int
InterfaceAcceptor< InterfaceT >::Connect( ComponentBase * providerComponent )
{
  InterfaceT * providerInterface = dynamic_cast< InterfaceT * >( providerComponent );
  if( !providerInterface )
32
  {
33
34
    //TODO log message?
    //std::cout << "providerComponent does not have required " << InterfaceName < InterfaceT >::Get() << std::endl;
35
36
37
    return 0;
  }
  // connect value interfaces
38
  this->Set( providerInterface ); // due to the input argument being uniquely defined in the multiple inheritance tree, all versions of Set() are accessible at component level
39
40
  return 1;
}
41

42
43
44
45
46
47
48
template< class InterfaceT >
bool
InterfaceAcceptor< InterfaceT >::CanAcceptConnectionFrom(ComponentBase * providerComponent)
{
  InterfaceT * providerInterface = dynamic_cast< InterfaceT * >(providerComponent);
  return bool(providerInterface);
}
49

50
//////////////////////////////////////////////////////////////////////////
51
template< typename AcceptingInterfaces, typename ProvidingInterfaces >
52
InterfaceStatus
53
SuperElastixComponent< AcceptingInterfaces, ProvidingInterfaces >::AcceptConnectionFrom( const char * interfacename, ComponentBase * other )
54
{
55
  return AcceptingInterfaces::ConnectFromImpl( interfacename, other );
56
57
}

58
59
60
61

template< typename AcceptingInterfaces, typename ProvidingInterfaces >
int
SuperElastixComponent< AcceptingInterfaces, ProvidingInterfaces >::AcceptConnectionFrom( ComponentBase * other )
62
{
63
  return AcceptingInterfaces::ConnectFromImpl( other );
64
}
65

66
template< typename AcceptingInterfaces, typename ProvidingInterfaces >
67
InterfaceStatus
68
69
70
71
72
SuperElastixComponent< AcceptingInterfaces, ProvidingInterfaces >
::CanAcceptConnectionFrom(ComponentBase* other, const InterfaceCriteriaType interfaceCriteria)
{
  return AcceptingInterfaces::CanAcceptConnectionFrom(other, interfaceCriteria);
}
73

74
//////////////////////////////////////////////////////////////////////////
75
template< typename FirstInterface, typename ... RestInterfaces >
76
InterfaceStatus
77
Accepting< FirstInterface, RestInterfaces ... >::ConnectFromImpl( const char * interfacename, ComponentBase * other )
78
{
79
80
  // does our component have an accepting interface called interfacename?
  if( InterfaceName< InterfaceAcceptor< FirstInterface >>::Get() == std::string( interfacename ) )
81
  {
82
    // cast always succeeds since we know via the template arguments of the component which InterfaceAcceptors its base classes are.
83
    InterfaceAcceptor< FirstInterface > * acceptIF = this;
84
85

    // See if the other component has the right interface and try to connect them
86
    if( 1 == acceptIF->Connect( other ) )
87
88
    {
      //success. By terminating this function, we assume only one interface listens to interfacename and that one connection with the other component can be made by this name
89
      return InterfaceStatus::success;
90
91
92
93
    }
    else
    {
      // interfacename was found, but other component doesn't match
94
      return InterfaceStatus::noprovider;
95
96
    }
  }
97
  return Accepting< RestInterfaces ... >::ConnectFromImpl( interfacename, other );
98
}
99

100
101
102
103

template< typename FirstInterface, typename ... RestInterfaces >
int
Accepting< FirstInterface, RestInterfaces ... >::ConnectFromImpl( ComponentBase * other )
104
{
105
  // cast always succeeds since we know via the template arguments of the component which InterfaceAcceptors its base classes are.
106
  InterfaceAcceptor< FirstInterface > * acceptIF = ( this );
107
108
109

  // See if the other component has the right interface and try to connect them
  // count the number of successes
110
  return acceptIF->Connect( other ) + Accepting< RestInterfaces ... >::ConnectFromImpl( other );
111
112
}

113

114
template< typename FirstInterface, typename ... RestInterfaces >
115
InterfaceStatus
116
117
118
Accepting< FirstInterface, RestInterfaces ... >::CanAcceptConnectionFrom(ComponentBase* other, const ComponentBase::InterfaceCriteriaType interfaceCriteria)
{

119
  InterfaceStatus restInterfacesStatus = Accepting< RestInterfaces ... >::CanAcceptConnectionFrom(other, interfaceCriteria);
120
  // if multiple interfaces were a success we do not have to check any further interfaces.
121
  if (restInterfacesStatus == InterfaceStatus::multiple)
122
  {
123
    return InterfaceStatus::multiple;
124
  }
125
126
127
  // We use the FirstInterface only (of each recursion level), thus the count can be 0 or 1
  unsigned int interfaceMeetsCriteria = Count<FirstInterface>::MeetsCriteria(interfaceCriteria);
  if (interfaceMeetsCriteria == 0) // InterfaceStatus::noaccepter;
128
  {
129
130
    // no new success, keep the status of previous recursion
    return restInterfacesStatus;
131
  }
132
  else // This "FirstInterface" of the component is an acceptor interface that fulfills the criteria
133
  {
134
135
    InterfaceAcceptor< FirstInterface > * acceptIF = (this);
    if (acceptIF->CanAcceptConnectionFrom(other))
136
    {
137
138
139
140
      // if a previous interface was a success, we can have either success or multiple (successes)
      if (restInterfacesStatus == InterfaceStatus::success)
        return InterfaceStatus::multiple;
      return InterfaceStatus::success;
141
    }
142
    else // InterfaceStatus::noprovider
143
    {
144
145
146
147
      // The found acceptor interface is not identical to a providing interface of the other component
      if (restInterfacesStatus == InterfaceStatus::noaccepter)
        return InterfaceStatus::noprovider;
      return restInterfacesStatus;
148
149
    }
  }
150
  // never reached
151
  return InterfaceStatus::noaccepter;
152
153
}

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

template< typename FirstInterface, typename ... RestInterfaces >
unsigned int
Accepting< FirstInterface, RestInterfaces ... >::CountMeetsCriteria(const ComponentBase::InterfaceCriteriaType interfaceCriteria)
{
  return Count<FirstInterface, RestInterfaces ... >::MeetsCriteria(interfaceCriteria);
}

template< typename FirstInterface, typename ... RestInterfaces >
unsigned int
Providing< FirstInterface, RestInterfaces ... >::CountMeetsCriteria(const ComponentBase::InterfaceCriteriaType interfaceCriteria)
{
  return Count<FirstInterface, RestInterfaces ... >::MeetsCriteria(interfaceCriteria);
}


Floris Berendsen's avatar
Floris Berendsen committed
170
template <typename FirstInterface, typename ... RestInterfaces>
171
unsigned int Count<FirstInterface, RestInterfaces ...>::MeetsCriteria(const ComponentBase::InterfaceCriteriaType interfaceCriteria)
Floris Berendsen's avatar
Floris Berendsen committed
172
173
174
175
176
177
178
179
180
{
  auto interfaceProperies = Properties< FirstInterface >::Get();
  for (const auto keyAndValue : interfaceCriteria)
  {
    auto && key = keyAndValue.first;
    auto && value = keyAndValue.second;
    if (interfaceProperies.count(key) != 1 || interfaceProperies[key].compare(value)!=0 )
    {
      // as soon as any of the criteria fails we break the loop and test the RestInterfaces
181
      return Count< RestInterfaces ... >::MeetsCriteria(interfaceCriteria);
Floris Berendsen's avatar
Floris Berendsen committed
182
183
184
    }
  }
  // if all criteria are met for this Interface we add 1 to the count and continue with the RestInterfaces
185
  return 1 + Count< RestInterfaces ... >::MeetsCriteria(interfaceCriteria);
Floris Berendsen's avatar
Floris Berendsen committed
186
187
};

Floris Berendsen's avatar
Floris Berendsen committed
188
} // end namespace selx
189

190
#endif // #define selxSuperElastixComponent_hxx