00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ITEMPAYLOADINTERNALS_P_H
00021 #define ITEMPAYLOADINTERNALS_P_H
00022
00023 #include <kpimutils/supertrait.h>
00024
00025 #include <QtCore/QtGlobal>
00026 #include <QtCore/QSharedPointer>
00027 #include <QtCore/QMetaType>
00028
00029 #include <boost/shared_ptr.hpp>
00030 #include <boost/type_traits/is_same.hpp>
00031 #include <boost/mpl/eval_if.hpp>
00032 #include <boost/mpl/identity.hpp>
00033 #include <boost/utility/enable_if.hpp>
00034
00035 #include <typeinfo>
00036
00037 #include "exception.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 namespace Akonadi {
00048 namespace Internal {
00049
00050 template <typename T>
00051 struct has_clone_method {
00052 private:
00053 template <typename S, S * (S::*)() const> struct sfinae {};
00054 struct No {};
00055 struct Yes { No no[2]; };
00056 template <typename S> static No test( ... );
00057 template <typename S> static Yes test( sfinae<S,&S::clone> * );
00058 public:
00059 static const bool value = sizeof( test<T>(0) ) == sizeof( Yes ) ;
00060 };
00061
00062 template <typename T, bool b>
00063 struct clone_traits_helper {
00064
00065
00066
00067 template <typename U>
00068 static T * clone( U ) { return 0; }
00069 };
00070
00071 template <typename T>
00072 struct clone_traits_helper<T,true> {
00073 static T * clone( T * t ) { return t ? t->clone() : 0 ; }
00074 };
00075
00076 template <typename T>
00077 struct clone_traits : clone_traits_helper<T, has_clone_method<T>::value> {};
00078
00079 template <typename T>
00080 struct shared_pointer_traits {
00081 static const bool defined = false;
00082 };
00083
00084 template <typename T>
00085 struct shared_pointer_traits< boost::shared_ptr<T> > {
00086 static const bool defined = true;
00087 typedef T element_type;
00088 template <typename S>
00089 struct make { typedef boost::shared_ptr<S> type; };
00090 typedef QSharedPointer<T> next_shared_ptr;
00091 };
00092
00093 template <typename T>
00094 struct shared_pointer_traits< QSharedPointer<T> > {
00095 static const bool defined = true;
00096 typedef T element_type;
00097 template <typename S>
00098 struct make { typedef QSharedPointer<S> type; };
00099 typedef boost::shared_ptr<T> next_shared_ptr;
00100 };
00101
00102 template <typename T>
00103 struct is_shared_pointer {
00104 static const bool value = shared_pointer_traits<T>::defined;
00105 };
00106
00107 template <typename T>
00108 struct get_hierarchy_root;
00109
00110 template <typename T, typename S>
00111 struct get_hierarchy_root_recurse
00112 : get_hierarchy_root<S> {};
00113
00114 template <typename T>
00115 struct get_hierarchy_root_recurse<T,T>
00116 : boost::mpl::identity<T> {};
00117
00118 template <typename T>
00119 struct get_hierarchy_root
00120 : get_hierarchy_root_recurse< T, typename ::KPIMUtils::SuperClass<T>::Type > {};
00121
00122 template <typename T>
00123 struct get_hierarchy_root< boost::shared_ptr<T> > {
00124 typedef boost::shared_ptr< typename get_hierarchy_root<T>::type > type;
00125 };
00126
00127 template <typename T>
00128 struct get_hierarchy_root< QSharedPointer<T> > {
00129 typedef QSharedPointer< typename get_hierarchy_root<T>::type > type;
00130 };
00131
00132
00139 template <typename T> struct PayloadTrait
00140 {
00142 typedef T ElementType;
00143
00144
00145 static int elementMetaTypeId() { return qMetaTypeId<T>(); }
00148 typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType;
00150 typedef T Type;
00154 typedef typename KPIMUtils::SuperClass<T>::Type SuperType;
00157 static const bool isPolymorphic = false;
00159 static inline bool isNull( const Type & ) { return true; }
00162 template <typename U> static inline Type castFrom( const U& )
00163 {
00164 throw PayloadException( "you should never get here" );
00165 }
00167 template <typename U> static inline bool canCastFrom( const U& )
00168 {
00169 return false;
00170 }
00172 template <typename U> static inline U castTo( const Type& )
00173 {
00174 throw PayloadException( "you should never get here" );
00175 }
00176 template <typename U> static T clone( const U & )
00177 {
00178 throw PayloadException( "clone: you should never get here" );
00179 }
00181 static const unsigned int sharedPointerId = 0;
00182 };
00183
00189 template <typename T> struct PayloadTrait<boost::shared_ptr<T> >
00190 {
00191 typedef T ElementType;
00192 static int elementMetaTypeId() { return qMetaTypeId<T*>(); }
00193 typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType;
00194 typedef boost::shared_ptr<ElementType> Type;
00195 typedef boost::shared_ptr<SuperElementType> SuperType;
00196 static const bool isPolymorphic = !boost::is_same<ElementType, SuperElementType>::value;
00197 static inline bool isNull( const Type &p ) { return p.get() == 0; }
00198 template <typename U> static inline Type castFrom( const boost::shared_ptr<U> &p )
00199 {
00200 const Type sp = boost::dynamic_pointer_cast<T,U>( p );
00201 if ( sp.get() != 0 || p.get() == 0 )
00202 return sp;
00203 throw PayloadException( "boost::dynamic_pointer_cast failed" );
00204 }
00205 template <typename U> static inline bool canCastFrom( const boost::shared_ptr<U> &p )
00206 {
00207 const Type sp = boost::dynamic_pointer_cast<T,U>( p );
00208 return sp.get() != 0 || p.get() == 0;
00209 }
00210 template <typename U> static inline boost::shared_ptr<U> castTo( const Type &p )
00211 {
00212 const boost::shared_ptr<U> sp = boost::dynamic_pointer_cast<U>( p );
00213 return sp;
00214 }
00215 static boost::shared_ptr<T> clone( const QSharedPointer<T> & t ) {
00216 if ( T * nt = clone_traits<T>::clone( t.data() ) )
00217 return boost::shared_ptr<T>( nt );
00218 else
00219 return boost::shared_ptr<T>();
00220 }
00221 static const unsigned int sharedPointerId = 1;
00222 };
00223
00229 template <typename T> struct PayloadTrait<QSharedPointer<T> >
00230 {
00231 typedef T ElementType;
00232 static int elementMetaTypeId() { return qMetaTypeId<T*>(); }
00233 typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType;
00234 typedef QSharedPointer<T> Type;
00235 typedef QSharedPointer<SuperElementType> SuperType;
00236 static const bool isPolymorphic = !boost::is_same<ElementType, SuperElementType>::value;
00237 static inline bool isNull( const Type &p ) { return p.isNull(); }
00238 template <typename U> static inline Type castFrom( const QSharedPointer<U> &p )
00239 {
00240 const Type sp = qSharedPointerDynamicCast<T,U>( p );
00241 if ( !sp.isNull() || p.isNull() )
00242 return sp;
00243 throw PayloadException( "qSharedPointerDynamicCast failed" );
00244 }
00245 template <typename U> static inline bool canCastFrom( const QSharedPointer<U> &p )
00246 {
00247 const Type sp = qSharedPointerDynamicCast<T,U>( p );
00248 return !sp.isNull() || p.isNull();
00249 }
00250 template <typename U> static inline QSharedPointer<U> castTo( const Type &p )
00251 {
00252 const QSharedPointer<U> sp = qSharedPointerDynamicCast<U,T>( p );
00253 return sp;
00254 }
00255 static QSharedPointer<T> clone( const boost::shared_ptr<T> & t ) {
00256 if ( T * nt = clone_traits<T>::clone( t.get() ) )
00257 return QSharedPointer<T>( nt );
00258 else
00259 return QSharedPointer<T>();
00260 }
00261 static const unsigned int sharedPointerId = 2;
00262 };
00263
00264
00265 }
00266
00272 struct PayloadBase
00273 {
00274 virtual ~PayloadBase() { }
00275 virtual PayloadBase * clone() const = 0;
00276 virtual const char* typeName() const = 0;
00277 };
00278
00284 template <typename T>
00285 struct Payload : public PayloadBase
00286 {
00287 Payload() {};
00288 Payload( const T& p ) : payload( p ) {}
00289
00290 PayloadBase * clone() const
00291 {
00292 return new Payload<T>( const_cast<Payload<T>* >(this)->payload);
00293 }
00294
00295 const char* typeName() const
00296 {
00297 return typeid(const_cast<Payload<T>*> (this)).name();
00298 }
00299
00300 T payload;
00301 };
00302
00307 template <typename T>
00308 struct Payload<T*> : public PayloadBase
00309 {
00310 };
00311
00312 namespace Internal {
00313
00318 template <typename T> inline Payload<T>* payload_cast( PayloadBase* payloadBase )
00319 {
00320 Payload<T> *p = dynamic_cast<Payload<T>*>( payloadBase );
00321
00322 if ( !p && payloadBase && strcmp( payloadBase->typeName(), typeid(p).name() ) == 0 ) {
00323 p = static_cast<Payload<T>*>( payloadBase );
00324 }
00325 return p;
00326 }
00327
00328 }
00329
00330 }
00331
00332
00333 #endif
00334