AusweisApp2
 Alle Klassen Namensbereiche Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Propertys Freundbeziehungen Makrodefinitionen
Env.h
gehe zur Dokumentation dieser Datei
1 /*
2  * \brief Runtime environment to create (mockable) objects.
3  *
4  * \copyright Copyright (c) 2017-2018 Governikus GmbH & Co. KG, Germany
5  */
6 
7 #pragma once
8 
9 #include <functional>
10 #include <memory>
11 #include <QMap>
12 #include <QMetaObject>
13 #include <QMetaType>
14 #include <QObject>
15 #include <QSharedPointer>
16 #include <QWeakPointer>
17 
18 #ifndef QT_NO_DEBUG
19 #include <QMutableVectorIterator>
20 #include <QVector>
21 #endif
22 
23 class test_Env;
24 
25 namespace governikus
26 {
27 
28 template<typename T> T* singleton(bool& pTakeOwnership);
29 template<typename T, typename ... Args> T createNewObject(Args&& ... pArgs);
30 
31 class Env
32 {
33  private:
34  friend class ::test_Env;
35  Q_DISABLE_COPY(Env)
36 
37 #ifndef QT_NO_DEBUG
38  class FuncWrapperBase
39  {
40  protected:
41  int mCounter = 0;
42 
43  public:
44  inline int getCounter() const
45  {
46  return mCounter;
47  }
48 
49 
50  inline void reset()
51  {
52  mCounter = 0;
53  }
54 
55 
56  virtual ~FuncWrapperBase();
57  };
58 
59  template<typename T, typename ... Args>
60  class FuncWrapper final
61  : public FuncWrapperBase
62  {
63  private:
64  const std::function<T(Args ...)> mFunc;
65 
66  public:
67  FuncWrapper(const std::function<T(Args ...)>& pFunc)
68  : mFunc(pFunc)
69  {
70  }
71 
72 
73  virtual ~FuncWrapper()
74  {
75  }
76 
77 
78  T operator()(Args&& ... pArgs)
79  {
80  ++mCounter;
81  return mFunc(std::forward<Args>(pArgs) ...);
82  }
83 
84 
85  };
86 
87  using Wrapper = std::shared_ptr<FuncWrapperBase>;
88  QVector<Wrapper> mInstancesCreator;
89 #endif
90 
91 
92  enum class Type
93  {
94  UNDEFINED,
95  OWNERSHIP,
96  UNMANAGED
97  };
98 
99  using Identifier = const char*;
100  QMap<Identifier, Type> mTypeInfo;
101  QMap<Identifier, void*> mInstancesUnmanaged;
102  QMap<Identifier, std::shared_ptr<void> > mInstancesOwnership;
103  QMap<Identifier, QWeakPointer<QObject> > mSharedInstances;
104 
105  static Env& getInstance();
106 
107  void storeSingleton(Identifier pId, void* pObject);
108  void storeSingleton(Identifier pId, std::shared_ptr<void> pObject);
109  void removeStoredSingleton(Identifier pId);
110  void* fetchStoredSingleton(Identifier pId) const;
111 
112  template<typename T>
113  typename std::enable_if<std::is_abstract<T>::value && std::is_destructible<T>::value, T*>::type storeSingleton(Identifier pId)
114  {
115  static_assert(std::has_virtual_destructor<T>::value, "Destructor must be virtual");
116 
117  bool ownership = true;
118  T* obj = singleton<T>(ownership);
119  Q_ASSERT(obj);
120  if (ownership)
121  {
122  storeSingleton(pId, std::shared_ptr<void>(obj));
123  }
124  else
125  {
126  storeSingleton(pId, obj);
127  }
128  return obj;
129  }
130 
131 
132  template<typename T>
133  typename std::enable_if<!std::is_destructible<T>::value, T*>::type storeSingleton(Identifier pId)
134  {
135  T* obj = &T::getInstance();
136  storeSingleton(pId, obj);
137  return obj;
138  }
139 
140 
141  template<typename T>
142  typename std::enable_if<std::is_default_constructible<T>::value, T*>::type storeSingleton(Identifier pId)
143  {
144  auto obj = std::make_shared<T>();
145  storeSingleton(pId, obj);
146  return obj.get();
147  }
148 
149 
150  template<typename T>
151  inline T* fetchSingleton()
152  {
153  #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
154  static_assert(QtPrivate::IsGadgetHelper<T>::IsRealGadget || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
155  "Singletons needs to be a Q_GADGET or an QObject/Q_OBJECT");
156  #else
157  static_assert(QtPrivate::IsGadgetHelper<T>::Value || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
158  "Singletons needs to be a Q_GADGET or an QObject/Q_OBJECT");
159  #endif
160 
161  Identifier id = T::staticMetaObject.className();
162  void* obj = fetchStoredSingleton(id);
163 
164  if (!obj)
165  {
166  obj = storeSingleton<T>(id);
167  }
168 
169  return static_cast<T*>(obj);
170  }
171 
172 
173  template<typename T, typename ... Args>
174  inline typename std::enable_if<!std::is_constructible<typename std::remove_pointer<T>::type, Args ...>::value, T>::type newObject(Args&& ... pArgs) const
175  {
176  static_assert(std::is_pointer<T>::value, "It is impossible to return implementation of interface by value. Use pointer or add constructor!");
177  auto obj = createNewObject<T>(std::forward<Args>(pArgs) ...);
178  Q_ASSERT(obj);
179  return obj;
180  }
181 
182 
183  template<typename T, typename ... Args>
184  inline typename std::enable_if<std::is_pointer<T>::value, T>::type internalNewObject(Args&& ... pArgs) const
185  {
186  using t = typename std::remove_pointer<T>::type;
187  return new t(std::forward<Args>(pArgs) ...);
188  }
189 
190 
191  template<typename T, typename ... Args>
192  inline typename std::enable_if<!std::is_pointer<T>::value, T>::type internalNewObject(Args&& ... pArgs) const
193  {
194  return T(std::forward<Args>(pArgs) ...);
195  }
196 
197 
198  template<typename T, typename ... Args>
199  inline typename std::enable_if<std::is_constructible<typename std::remove_pointer<T>::type, Args ...>::value, T>::type newObject(Args&& ... pArgs) const
200  {
201  return internalNewObject<T>(std::forward<Args>(pArgs) ...);
202  }
203 
204 
205  template<typename T, typename ... Args>
206  T createObject(Args&& ... pArgs) const
207  {
208 #ifndef QT_NO_DEBUG
209  for (auto& mock : qAsConst(mInstancesCreator))
210  {
211  auto creator = dynamic_cast<FuncWrapper<T, Args ...>*>(mock.get());
212  if (creator)
213  {
214  return (*creator)(std::forward<Args>(pArgs) ...);
215  }
216  }
217 #endif
218 
219  return newObject<T>(std::forward<Args>(pArgs) ...);
220  }
221 
222 
223  protected:
224  Env();
225  ~Env();
226 
227  public:
228  template<typename T>
229  static T* getSingleton()
230  {
231  return getInstance().fetchSingleton<T>();
232  }
233 
234 
235  template<typename T, typename ... Args>
236  static T create(Args&& ... pArgs)
237  {
238  return getInstance().createObject<T>(std::forward<Args>(pArgs) ...);
239  }
240 
241 
242  template<typename T>
243  static QSharedPointer<T> getShared()
244  {
245  #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
246  static_assert(QtPrivate::IsGadgetHelper<T>::IsRealGadget || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
247  "Shared class needs to be a Q_GADGET or an QObject/Q_OBJECT");
248  #else
249  static_assert(QtPrivate::IsGadgetHelper<T>::Value || QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value,
250  "Shared class needs to be a Q_GADGET or an QObject/Q_OBJECT");
251  #endif
252 
253  auto& holder = getInstance().mSharedInstances;
254  const auto* className = T::staticMetaObject.className();
255 
256  QSharedPointer<T> shared = qSharedPointerCast<T>(holder.value(className));
257  if (!shared)
258  {
259  shared = QSharedPointer<T>::create();
260  holder.insert(className, shared.toWeakRef());
261  }
262 
263  return shared;
264  }
265 
266 
267 #ifndef QT_NO_DEBUG
268  static void resetCounter();
269  static void clear();
270  static void set(const QMetaObject& pMetaObject, void* pObject = nullptr);
271  static void set(const QMetaObject& pMetaObject, std::shared_ptr<void> pObject);
272 
273  template<typename T, typename U>
274  static U* getSingleton()
275  {
276  return dynamic_cast<U*>(getSingleton<T>());
277  }
278 
279 
280  template<typename T, typename ... Args>
281  static int getCounter()
282  {
283  for (const auto& mock : qAsConst(getInstance().mInstancesCreator))
284  {
285  if (dynamic_cast<const FuncWrapper<T, Args ...>*>(mock.get()))
286  {
287  return mock->getCounter();
288  }
289  }
290 
291  return -1; // There is no mock... use setCreator!
292  }
293 
294 
295  template<typename T, typename ... Args>
296  static void setCreator(const std::function<T(Args ...)>& pFunc)
297  {
298  Q_ASSERT(pFunc);
299 
300  auto& holder = getInstance().mInstancesCreator;
301  const auto& value = Wrapper(new FuncWrapper<T, Args ...>(pFunc));
302 
303  QMutableVectorIterator<Wrapper> iter(holder);
304  while (iter.hasNext())
305  {
306  iter.next();
307  if (dynamic_cast<const FuncWrapper<T, Args ...>*>(iter.value().get()))
308  {
309  iter.setValue(value);
310  return;
311  }
312  }
313 
314  holder << value;
315  }
316 
317 
318  static void setShared(const QMetaObject& pMetaObject, QSharedPointer<QObject> pObject = QSharedPointer<QObject>());
319 #endif
320 
321 };
322 
323 } /* namespace governikus */
static T * getSingleton()
Definition: Env.h:229
static void clear()
Definition: Env.cpp:101
static void resetCounter()
Definition: Env.cpp:92
~Env()
Definition: Env.cpp:20
static void set(const QMetaObject &pMetaObject, void *pObject=nullptr)
Definition: Env.cpp:112
T createNewObject(Args &&...pArgs)
static void setShared(const QMetaObject &pMetaObject, QSharedPointer< QObject > pObject=QSharedPointer< QObject >())
Definition: Env.cpp:129
#define T(v)
Definition: http_parser.cpp:234
static void setCreator(const std::function< T(Args...)> &pFunc)
Definition: Env.h:296
static U * getSingleton()
Definition: Env.h:274
Env()
Definition: Env.cpp:15
T * singleton(bool &pTakeOwnership)
Definition: Env.h:31
static T create(Args &&...pArgs)
Definition: Env.h:236
static int getCounter()
Definition: Env.h:281
static QSharedPointer< T > getShared()
Definition: Env.h:243