@ -1,5 +1,6 @@ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "serviceregistry.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "serviceregistry_p.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "qtmvvmcore_logging_p.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  <QtCore/QGlobalStatic>  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  <QtCore/QRegularExpression>  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -22,17 +23,29 @@ ServiceRegistry *ServiceRegistry::instance() 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					void  ServiceRegistry : : registerService ( const  QByteArray  & iid ,  const  QMetaObject  * metaObject )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						QMutexLocker  _ ( & d - > serviceMutex ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						Q_ASSERT ( ! d - > services . contains ( iid ) ) ;  //TODO exception
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						if ( d - > services . contains ( iid ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							throw  ServiceExistsException ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						d - > services . insert ( iid ,  QSharedPointer < ServiceRegistryPrivate : : MetaServiceInfo > : : create ( metaObject ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					void  ServiceRegistry : : registerService ( const  QByteArray  & iid ,  const  std : : function < QObject * ( const  QObjectList  & ) >  & fn ,  QByteArrayList  injectables )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						QMutexLocker  _ ( & d - > serviceMutex ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						Q_ASSERT ( ! d - > services . contains ( iid ) ) ;  //TODO exception
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						if ( d - > services . contains ( iid ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							throw  ServiceExistsException ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						d - > services . insert ( iid ,  QSharedPointer < ServiceRegistryPrivate : : FnServiceInfo > : : create ( fn ,  injectables ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QObject  * ServiceRegistry : : acquireInstanceObject ( const  QByteArray  & iid )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						QMutexLocker  _ ( & d - > serviceMutex ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						auto  ref  =  d - > services . value ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						if ( ref )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							return  ref - > instance ( d . data ( ) ,  iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						else  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							throw  ServiceDependencyException ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					// ------------- Private Implementation -------------
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					ServiceRegistryPrivate : : ServiceRegistryPrivate ( )  :  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -52,10 +65,16 @@ ServiceRegistryPrivate::ServiceInfo::~ServiceInfo() 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							QMetaObject : : invokeMethod ( _instance ,  " deleteLater " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QObject  * ServiceRegistryPrivate : : ServiceInfo : : instance ( ServiceRegistryPrivate  * d )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QObject  * ServiceRegistryPrivate : : ServiceInfo : : instance ( ServiceRegistryPrivate  * d ,  const  QByteArray  & iid )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						if ( ! _instance )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						if ( ! _instance )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							logDebug ( )  < <  " Constructing service of type "  < <  iid ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							_instance  =  construct ( d ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							if ( ! _instance )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								throw  ServiceConstructionException ( " Failed to construct service of type  "  +  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
																   iid  +  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
																   "  with unknown error " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						return  _instance ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -69,8 +88,12 @@ ServiceRegistryPrivate::FnServiceInfo::FnServiceInfo(const std::function<QObject 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QObject  * ServiceRegistryPrivate : : FnServiceInfo : : construct ( ServiceRegistryPrivate  * d )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						QObjectList  params ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						foreach ( auto  inj ,  injectables )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							params . append ( d - > services . value ( inj ) - > instance ( d ) ) ; //TODO exception
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						foreach ( auto  iid ,  injectables )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							auto  ref  =  d - > services . value ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							if ( ! ref )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								throw  ServiceDependencyException ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							params . append ( ref - > instance ( d ,  iid ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						return  creator ( params ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -83,26 +106,117 @@ ServiceRegistryPrivate::MetaServiceInfo::MetaServiceInfo(const QMetaObject *meta 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QObject  * ServiceRegistryPrivate : : MetaServiceInfo : : construct ( ServiceRegistryPrivate  * d )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						auto  instance  =  metaObject - > newInstance ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						Q_ASSERT ( instance ) ;  //TODO exception
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						if ( ! instance )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							throw  ServiceConstructionException ( QByteArrayLiteral ( " Failed to construct object of type  " )  +  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
															   metaObject - > className ( )  +  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
															   QByteArrayLiteral ( "  - make shure there is an invokable constructor of the format: Q_INVOKABLE MyClass(QObject*) " ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						static  QRegularExpression  nameRegex ( QStringLiteral ( R " __(^__qtmvvm_inject_(.+)$)__ " ) ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
															QRegularExpression : : OptimizeOnFirstUsageOption ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						try  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							for ( auto  i  =  0 ;  i  <  metaObject - > propertyCount ( ) ;  i + + )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								auto  prop  =  metaObject - > property ( i ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								auto  match  =  nameRegex . match ( QString : : fromUtf8 ( prop . name ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								if ( match . hasMatch ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									auto  tPropIndex  =  metaObject - > indexOfProperty ( qUtf8Printable ( match . captured ( 1 ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								if ( tPropIndex  = =  - 1 )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									continue ;  //TODO warning
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									if ( tPropIndex  = =  - 1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
										logWarning ( ) . noquote ( )  < <  " Found hint to inject property "  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
															   < <  match . captured ( 1 )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
															   < <  " but no property of that name was found " ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
										continue ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									auto  tProp  =  metaObject - > property ( tPropIndex ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								auto  inject  =  prop . read ( instance ) . toByteArray ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								auto  injObj  =  d - > services . value ( inject ) - > instance ( d ) ;  //TODO exception
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									auto  iid  =  prop . read ( instance ) . toByteArray ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									auto  ref  =  d - > services . value ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									if ( ! ref )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
										throw  ServiceDependencyException ( iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									auto  injObj  =  ref - > instance ( d ,  iid ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
									tProp . write ( instance ,  QVariant : : fromValue ( injObj ) ) ;  //TODO check if casting works
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						//TODO call "init" method
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							auto  initMethod  =  metaObject - > indexOfMethod ( " qtmvvm_init() " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							if ( initMethod  ! =  - 1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								auto  method  =  metaObject - > method ( initMethod ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
								method . invoke ( instance ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							return  instance ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						}  catch  ( . . . )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							instance - > deleteLater ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
							throw ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					// ------------- Exceptions Implementation -------------
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					ServiceExistsException : : ServiceExistsException ( const  QByteArray  & iid )  :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						_msg ( " An interface with the type id  \" "  +  iid  +  " \"  has already been registered " )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					ServiceExistsException : : ServiceExistsException ( const  ServiceExistsException  *  const  other )  :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						_msg ( other - > _msg )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  char  * ServiceExistsException : : what ( )  const  noexcept  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						return  _msg . constData ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					void  ServiceExistsException : : raise ( )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						throw  ( * this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QException  * ServiceExistsException : : clone ( )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						return  new  ServiceExistsException ( this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					ServiceConstructionException : : ServiceConstructionException ( const  QByteArray  & message )  :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						_msg ( message )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					ServiceConstructionException : : ServiceConstructionException ( const  ServiceConstructionException  *  const  other )  :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						_msg ( other - > _msg )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  char  * ServiceConstructionException : : what ( )  const  noexcept  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						return  _msg . constData ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					void  ServiceConstructionException : : raise ( )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						throw  ( * this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QException  * ServiceConstructionException : : clone ( )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						return  new  ServiceConstructionException ( this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					ServiceDependencyException : : ServiceDependencyException ( const  QByteArray  & iid )  :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						ServiceConstructionException ( " Failed to construct service because of missing dependency:  "  +  iid )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					ServiceDependencyException : : ServiceDependencyException ( const  ServiceDependencyException  *  const  other )  :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						ServiceConstructionException ( other )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{ }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					void  ServiceDependencyException : : raise ( )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						throw  ( * this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					QException  * ServiceDependencyException : : clone ( )  const  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
						return  new  ServiceDependencyException ( this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}