20 #ifndef ITEMPAYLOADINTERNALS_P_H 
   21 #define ITEMPAYLOADINTERNALS_P_H 
   23 #include <kpimutils/supertrait.h> 
   25 #include <QtCore/QtGlobal> 
   26 #include <QtCore/QSharedPointer> 
   27 #include <QtCore/QMetaType> 
   29 #include <boost/shared_ptr.hpp> 
   30 #include <boost/type_traits/is_same.hpp> 
   31 #include <boost/mpl/eval_if.hpp> 
   32 #include <boost/mpl/identity.hpp> 
   33 #include <boost/utility/enable_if.hpp> 
   37 #include "exception.h" 
   51 struct has_clone_method {
 
   53     template <
typename S, S * (S::*)() const> 
struct sfinae {};
 
   55     struct Yes { No no[2]; };
 
   56     template <
typename S> 
static No  test( ... );
 
   57     template <
typename S> 
static Yes test( sfinae<S,&S::clone> * );
 
   59     static const bool value = 
sizeof( test<T>(0) ) == 
sizeof( Yes ) ;
 
   62 template <
typename T, 
bool b>
 
   63 struct clone_traits_helper {
 
   68     static T * clone( U ) { 
return 0; }
 
   72 struct clone_traits_helper<T,true> {
 
   73     static T * clone( T * t ) { 
return t ? t->clone() : 0 ; }
 
   77 struct clone_traits : clone_traits_helper<T, has_clone_method<T>::value> {};
 
   80 struct shared_pointer_traits {
 
   81     static const bool defined = 
false;
 
   85 struct shared_pointer_traits< boost::shared_ptr<T> > {
 
   86     static const bool defined = 
true;
 
   87     typedef T element_type;
 
   89     struct make { 
typedef boost::shared_ptr<S> type; };
 
   90     typedef QSharedPointer<T> next_shared_ptr;
 
   94 struct shared_pointer_traits< QSharedPointer<T> > {
 
   95     static const bool defined = 
true;
 
   96     typedef T element_type;
 
   98     struct make { 
typedef QSharedPointer<S> type; };
 
   99     typedef boost::shared_ptr<T> next_shared_ptr;
 
  102 template <
typename T>
 
  103 struct is_shared_pointer {
 
  104     static const bool value = shared_pointer_traits<T>::defined;
 
  107 template <
typename T>
 
  108 struct get_hierarchy_root;
 
  110 template <
typename T, 
typename S>
 
  111 struct get_hierarchy_root_recurse
 
  112     : get_hierarchy_root<S> {};
 
  114 template <
typename T>
 
  115 struct get_hierarchy_root_recurse<T,T>
 
  116     : boost::mpl::identity<T> {};
 
  118 template <
typename T>
 
  119 struct get_hierarchy_root
 
  120     : get_hierarchy_root_recurse< T, typename ::KPIMUtils::SuperClass<T>::Type > {};
 
  122 template <
typename T>
 
  123 struct get_hierarchy_root< boost::shared_ptr<T> > {
 
  124     typedef boost::shared_ptr< typename get_hierarchy_root<T>::type > type;
 
  127 template <
typename T>
 
  128 struct get_hierarchy_root< QSharedPointer<T> > {
 
  129     typedef QSharedPointer< typename get_hierarchy_root<T>::type > type;
 
  138 template <
typename T> 
struct PayloadTrait
 
  141   typedef T ElementType;
 
  144   static int elementMetaTypeId() { 
return qMetaTypeId<T>(); }
 
  147   typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType;
 
  153   typedef typename KPIMUtils::SuperClass<T>::Type SuperType;
 
  156   static const bool isPolymorphic = 
false;
 
  158   static inline bool isNull( 
const Type & ) { 
return true; }
 
  161   template <
typename U> 
static inline Type castFrom( 
const U& )
 
  163     throw PayloadException( 
"you should never get here" );
 
  166   template <
typename U> 
static inline bool canCastFrom( 
const U& )
 
  171   template <
typename U> 
static inline U castTo( 
const Type& )
 
  173     throw PayloadException( 
"you should never get here" );
 
  175   template <
typename U> 
static T clone( 
const U & )
 
  177     throw PayloadException( 
"clone: you should never get here" );
 
  180   static const unsigned int sharedPointerId = 0;
 
  188 template <
typename T> 
struct PayloadTrait<boost::shared_ptr<T> >
 
  190   typedef T ElementType;
 
  191   static int elementMetaTypeId() { 
return qMetaTypeId<T*>(); }
 
  192   typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType;
 
  193   typedef boost::shared_ptr<ElementType> Type;
 
  194   typedef boost::shared_ptr<SuperElementType> SuperType;
 
  195   static const bool isPolymorphic = !boost::is_same<ElementType, SuperElementType>::value;
 
  196   static inline bool isNull( 
const Type &p ) { 
return p.get() == 0; }
 
  197   template <
typename U> 
static inline Type castFrom( 
const boost::shared_ptr<U> &p )
 
  199     const Type sp = boost::dynamic_pointer_cast<T,U>( p );
 
  200     if ( sp.get() != 0 || p.get() == 0 )
 
  202     throw PayloadException( 
"boost::dynamic_pointer_cast failed" );
 
  204   template <
typename U> 
static inline bool canCastFrom( 
const boost::shared_ptr<U> &p )
 
  206     const Type sp = boost::dynamic_pointer_cast<T,U>( p );
 
  207     return sp.get() != 0 || p.get() == 0;
 
  209   template <
typename U> 
static inline boost::shared_ptr<U> castTo( 
const Type &p )
 
  211     const boost::shared_ptr<U> sp = boost::dynamic_pointer_cast<U>( p );
 
  214   static boost::shared_ptr<T> clone( 
const QSharedPointer<T> & t ) {
 
  215       if ( T * nt = clone_traits<T>::clone( t.data() ) )
 
  216           return boost::shared_ptr<T>( nt );
 
  218           return boost::shared_ptr<T>();
 
  220   static const unsigned int sharedPointerId = 1;
 
  228 template <
typename T> 
struct PayloadTrait<QSharedPointer<T> >
 
  230   typedef T ElementType;
 
  231   static int elementMetaTypeId() { 
return qMetaTypeId<T*>(); }
 
  232   typedef typename KPIMUtils::SuperClass<T>::Type SuperElementType;
 
  233   typedef QSharedPointer<T> Type;
 
  234   typedef QSharedPointer<SuperElementType> SuperType;
 
  235   static const bool isPolymorphic = !boost::is_same<ElementType, SuperElementType>::value;
 
  236   static inline bool isNull( 
const Type &p ) { 
return p.isNull(); }
 
  237   template <
typename U> 
static inline Type castFrom( 
const QSharedPointer<U> &p )
 
  239     const Type sp = qSharedPointerDynamicCast<T,U>( p );
 
  240     if ( !sp.isNull() || p.isNull() )
 
  242     throw PayloadException( 
"qSharedPointerDynamicCast failed" );
 
  244   template <
typename U> 
static inline bool canCastFrom( 
const QSharedPointer<U> &p )
 
  246     const Type sp = qSharedPointerDynamicCast<T,U>( p );
 
  247     return !sp.isNull() || p.isNull();
 
  249   template <
typename U> 
static inline QSharedPointer<U> castTo( 
const Type &p )
 
  251     const QSharedPointer<U> sp = qSharedPointerDynamicCast<U,T>( p );
 
  254   static QSharedPointer<T> clone( 
const boost::shared_ptr<T> & t ) {
 
  255       if ( T * nt = clone_traits<T>::clone( t.get() ) )
 
  256           return QSharedPointer<T>( nt );
 
  258           return QSharedPointer<T>();
 
  260   static const unsigned int sharedPointerId = 2;
 
  272     virtual ~PayloadBase() { }
 
  273     virtual PayloadBase * clone() 
const = 0;
 
  274     virtual const char* typeName() 
const = 0;
 
  282 template <
typename T>
 
  283 struct Payload : 
public PayloadBase
 
  286     Payload( 
const T& p ) : payload( p ) {}
 
  288     PayloadBase * clone()
 const 
  290         return new Payload<T>( 
const_cast<Payload<T>* 
>(
this)->payload);
 
  293     const char* typeName()
 const 
  295       return typeid(
const_cast<Payload<T>*
> (
this)).name();
 
  305 template <
typename T>
 
  306 struct Payload<T*> : 
public PayloadBase
 
  316 template <
typename T> 
inline Payload<T>* payload_cast( PayloadBase* payloadBase )
 
  318   Payload<T> *p = 
dynamic_cast<Payload<T>*
>( payloadBase );
 
  320   if ( !p && payloadBase && strcmp( payloadBase->typeName(), 
typeid(p).name() ) == 0 ) {
 
  321     p = 
static_cast<Payload<T>*
>( payloadBase );