Skip to content
Snippets Groups Projects
WrapperAbstraction.hpp 6.32 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * WrapperAbstraction.hpp
     *
     *  Created on: 11. 7. 2017
     *	  Author: Jan Travnicek
     */
    
    #ifndef _WRAPPER_ABSTRACTION_HPP_
    #define _WRAPPER_ABSTRACTION_HPP_
    
    #include <abstraction/OperationAbstraction.hpp>
    
    class UnspecifiedType {
    };
    
    
    template < class ... ParamTypes >
    
    class BaseWrapperAbstraction : public OperationAbstraction {
    
    	std::function < std::shared_ptr < OperationAbstraction > ( ParamTypes ... ) > m_WrapperFinder;
    
    
    	std::shared_ptr < OperationAbstraction > m_abstraction;
    
    	ext::array < std::pair < std::shared_ptr < OperationAbstraction >, bool >, sizeof ... ( ParamTypes ) > m_params;
    
    protected:
    	void evalAbstractionFunction ( ) {
    		m_abstraction = abstraction::apply < ParamTypes ... > ( m_WrapperFinder, m_params );
    	}
    
    	std::shared_ptr < OperationAbstraction > & getAbstraction ( ) {
    		return m_abstraction;
    	}
    
    	const std::shared_ptr < OperationAbstraction > & getAbstraction ( ) const {
    		return m_abstraction;
    	}
    
    
    	void attachInputsToAbstraction ( ) {
    		for ( size_t index = 0; index < sizeof ... ( ParamTypes ); ++ index )
    			if ( ! this->m_abstraction->attachInput ( m_params [ index ].first, index, m_params [ index ].second, true ) )
    				throw std::invalid_argument ( "Can't connect param " + this->m_abstraction->getParamType ( index ) + " at " + ext::to_string ( index ) + " of wrapped algorithm with result of type " + m_params [ index ].first->getReturnType ( ) + "." );
    
    	}
    
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    	BaseWrapperAbstraction ( std::function < std::shared_ptr < OperationAbstraction > ( ParamTypes ... ) > wrapperFinder ) : m_WrapperFinder ( std::move ( wrapperFinder ) ) {
    
    		for ( size_t i = 0; i < sizeof ... ( ParamTypes ); ++ i ) {
    
    			m_params [ i ].first = nullptr;
    			m_params [ i ].second = false;
    		}
    
    	bool attachInput ( const std::shared_ptr < OperationAbstraction > & input, size_t index, bool move, bool checkInput ) override {
    
    		if ( index >= m_params.size ( ) )
    
    			throw std::invalid_argument ( "Parameter index " + ext::to_string ( index ) + " out of bounds.");
    
    		if ( input == nullptr )
    			return false;
    
    		if ( checkInput && ! this->checkInput ( input, index ) )
    
    			return false;
    
    		m_params [ index ].first = input;
    		m_params [ index ].second = move;
    
    		return true;
    
    	bool detachInput ( size_t index ) override {
    
    		if ( index >= m_params.size ( ) )
    
    			throw std::invalid_argument ( "Parameter index " + ext::to_string ( index ) + " out of bounds.");
    
    		m_params [ index ].first = nullptr;
    		m_params [ index ].second = false;
    
    		return true;
    
    	bool checkInput ( const std::shared_ptr < OperationAbstraction > & input, size_t index ) const override {
    
    		return abstraction::checkInput < ValueInterface < std::decay_t < ParamTypes > > ... > ( input, index );
    
    	bool inputsAttached ( ) const override {
    
    		for ( const std::pair < std::shared_ptr < OperationAbstraction >, bool > & param : m_params )
    			if ( ! param.first )
    				return false;
    
    		return true;
    
    		if ( ! inputsAttached ( ) )
    			return false;
    
    
    		if ( this->evaluated ( ) )
    
    		for ( const std::pair < std::shared_ptr < OperationAbstraction >, bool > & param : m_params )
    			if ( ! param.first->eval ( ) )
    				return false;
    
    	size_t numberOfParams ( ) const override {
    
    		return sizeof ... ( ParamTypes );
    	}
    
    
    	bool evaluated ( ) const override {
    		return ( bool ) m_abstraction && m_abstraction->evaluated ( );
    
    	ext::type_index getParamTypeIndex ( size_t index ) const override {
    
    Jan Travnicek's avatar
    Jan Travnicek committed
    		return abstraction::paramType < ParamTypes ... > ( index );
    
    	ext::set < abstraction::ParamQualifiers::ParamQualifier > getParamTypeQualifiers ( size_t index ) const override {
    
    Jan Travnicek's avatar
    Jan Travnicek committed
    		return abstraction::paramTypeQualifiers < ParamTypes ... > ( index );
    
    	std::shared_ptr < abstraction::OperationAbstraction > getProxyAbstraction ( ) override {
    
    		if ( this->evaluated ( ) )
    
    			return this->m_abstraction->getProxyAbstraction ( );
    
    		else
    			throw std::domain_error ( "Proxy abstraction not avaiable before evaluation." );
    	}
    
    	std::shared_ptr < abstraction::OperationAbstraction > getVariableOperationAbstraction ( ) override {
    		if ( this->evaluated ( ) )
    			return this->getAbstraction ( )->getProxyAbstraction ( )->getVariableOperationAbstraction ( );
    		else
    			throw std::domain_error ( "Variable deduction not available before evaluation." );
    	}
    
    
    };
    
    template < class ReturnType, class ... ParamTypes >
    class WrapperAbstraction : public BaseWrapperAbstraction < ParamTypes ... > {
    public:
    	WrapperAbstraction ( std::function < std::shared_ptr < OperationAbstraction > ( ParamTypes ... ) > wrapperFinder ) : BaseWrapperAbstraction < ParamTypes ... > ( wrapperFinder ) {
    	}
    
    
    		this->evalAbstractionFunction ( );
    
    		if ( this->getAbstraction ( )->getReturnTypeIndex ( ) != this->getReturnTypeIndex ( ) )
    
    			throw std::domain_error ( "Expected and provided types do not match" );
    
    
    		this->attachInputsToAbstraction ( );
    
    		return this->getAbstraction ( )->eval ( );
    
    	ext::type_index getReturnTypeIndex ( ) const override {
    
    		return ext::type_index ( typeid ( ReturnType ) );
    
    	ext::set < abstraction::ParamQualifiers::ParamQualifier > getReturnTypeQualifiers ( ) const override {
    
    		return abstraction::ParamQualifiers::paramQualifiers < ReturnType > ( );
    	}
    
    
    template < class ... ParamTypes >
    class WrapperAbstraction < UnspecifiedType, ParamTypes ... > : public BaseWrapperAbstraction < ParamTypes ... > {
    public:
    	WrapperAbstraction ( std::function < std::shared_ptr < OperationAbstraction > ( ParamTypes ... ) > wrapperFinder ) : BaseWrapperAbstraction < ParamTypes ... > ( wrapperFinder ) {
    	}
    
    
    		this->evalAbstractionFunction ( );
    
    		this->attachInputsToAbstraction ( );
    
    		return this->getAbstraction ( )->eval ( );
    
    	ext::type_index getReturnTypeIndex ( ) const override {
    
    		if ( this->evaluated ( ) )
    
    			return this->getAbstraction ( )->getProxyAbstraction ( )->getReturnTypeIndex ( );
    
    			throw std::domain_error ( "Return type unknown before evaluation." );
    
    	ext::set < abstraction::ParamQualifiers::ParamQualifier > getReturnTypeQualifiers ( ) const override {
    
    		if ( this->evaluated ( ) )
    
    			return this->getAbstraction ( )->getProxyAbstraction ( )->getReturnTypeQualifiers ( );
    
    		else
    			throw std::domain_error ( "Return type qualifiers unknown before evaluation." );
    	}
    
    
    } /* namespace abstraction */
    
    #endif /* _WRAPPER_ABSTRACTION_HPP_ */