Pusher.hh 8.56 KB
/*
 * Pusher.hh
 *
 *  Created on: Jan 30, 2019
 *      Author: AKKA
 */

#ifndef PUSHER_H_
#define PUSHER_H_

#include <vector>
#include "ParamData.hh"


#include "SpeasyProxyParamData.hh"

namespace AMDA {
namespace SpeasyProxyInterface {

// int getNbDataByPacket(ConstantParamType paramType, int dim1, int dim2);

/**
 * @class PusherBase
 * @details This class is the operation responsible to transform raw data from local file into a ParamData
 * of the corresponding type ( scalar or vector of short or int or float or double or ... type).
 */
struct PusherBase {
public:
	/*
	 * @brief Constructor
	 */
	PusherBase (int dim1, int dim2, SpeasyProxyContainerType container, 
                SpeasyProxyParamType type) : 
                    _paramData(NULL), _dim1(dim1), _dim2(dim2), 
                    _fillValue(NAN), _container(container), _type(type)
	{
	}

	/*
	 * @brief Destructor
	 */
	virtual ~PusherBase()
	{
	}

	/*
	 * @brief Get the ParamData
	 */
	AMDA::Parameters::ParamData* getParamData(void)
	{
		return _paramData;
	}

    SpeasyProxyContainerType getContainer(void)
    {
        return _container;
    }

    int getDim1() {
        return _dim1;
    }

    int getDim2() {
        return _dim2;
    }

    SpeasyProxyParamType getType() {
        return _type;
    }

    void setFillValue(double fillValue) {
        _fillValue = fillValue;
    }

	/*
	 * @brief Virtual method to put a packet in the ParamData
	 */
	virtual int put(SpeasyProxyParamDataPacket* packet) = 0;

    /*
	 * @brief Virtual method to put a NAN in the ParamData
	 */
    virtual void putNaN() = 0;

protected:
	/*
	 * @brief Pointer to the paramData
	 */
	AMDA::Parameters::ParamData* _paramData;

	/*
	 * @brief For Vector and Tab2D dimension
	 */
	int _dim1;

	/*
	 * @brief For Tab2D dimension
	 */
	int _dim2;

	/*
	 * @brief Nb data returned by one packet
	 */
	// int _nbDataByPacket;

    /*
	 * @brief Fill value
	 */
    double _fillValue;

    SpeasyProxyContainerType _container;

    SpeasyProxyParamType _type;
};


template <SpeasyProxyParamType type>
struct MapType { typedef void Type; };

template <> struct MapType<SpeasyProxyParamType::TYPE_SHORT>  { typedef short Type; };
template <> struct MapType<SpeasyProxyParamType::TYPE_INT>  { typedef int Type; };
template <> struct MapType<SpeasyProxyParamType::TYPE_FLOAT>  { typedef float Type; };
template <> struct MapType<SpeasyProxyParamType::TYPE_DOUBLE> { typedef double Type; };


template<SpeasyProxyParamType type, SpeasyProxyContainerType container = CONTAINER_VECTOR>
class Pusher;

/**
 * @brief Pusher implementation for the Tab2D.
 */
template<SpeasyProxyParamType type>
class Pusher<type,CONTAINER_MATRIX> : public PusherBase
{
public:
	/*
	 * @brief Define some usefull types
	 */
	typedef typename MapType<type>::Type BaseElemenType;
	typedef AMDA::Parameters::Tab2DData<BaseElemenType> ElemenType;
	typedef AMDA::Parameters::ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	/*
	 * @brief Constructor
	 */
	Pusher(int dim1, int dim2) : PusherBase( dim1, dim2, CONTAINER_MATRIX, type)
	{
		_paramData = _specParamData = createParamData();
		// _nbDataByPacket = getNbDataByPacket(type, dim1, dim2);
	}

	/*
	 * @brief Put packet in a "vector" ParamData
	 */
	virtual int put(SpeasyProxyParamDataPacket* packet)
	{
		//ParamData is created, add data

		_specParamData->getDataList().resize(packet->getNbData());

		BaseElemenType fillEl = _fillValue;

		for (int index = 0; index < packet->getNbData(); ++index)
		{
			//get time
			double time = packet->getTime(index);
			//this element will be deleted by the Container designed by "_specParamData->getDataList()"
			ElemenType elem = ElemenType(packet->getDim1Size(),packet->getDim2Size());
			for (int dim1Index = 0;  dim1Index < packet->getDim1Size(); ++dim1Index)
			{
				for (int dim2Index = 0;  dim2Index < packet->getDim2Size(); ++dim2Index)
				{
					BaseElemenType baseElem;
					//get data element
					if (packet->getDataValue(&baseElem,index,dim1Index,dim2Index))
					{
						if (!isnan(_fillValue))
						    if (baseElem == fillEl)
					        	baseElem << NotANumber();
					}
					else
						baseElem << NotANumber();
					elem[dim1Index][dim2Index] = baseElem;
				}
			}

			//push time and element in the ParamData
			_specParamData->getDataList().push_back(elem);
			_specParamData->getTimeList().push_back(time);
		}

		//return nb of processed records
		return packet->getNbData();

		return 0;
	}

    virtual void putNaN() {
		_specParamData->getDataList().resize(1);
		ElemenType nanElem = ElemenType(_dim1,_dim2);
		for(int i = 0; i < _dim1; ++i) {
			for(int j = 0; j < _dim2; ++j) {
				nanElem[i][j] << NotANumber();
			}
		}
		_specParamData->getDataList().push_back(nanElem);
	}

	/*
	 * @brief ParamData creation
	 */
	SpecParamData* createParamData()
	{
		return new AMDA::Parameters::ParamDataSpec<AMDA::Parameters::Tab2DData<typename MapType<type>::Type> >(_dim1,_dim2);
	}
};

/**
 * @brief Pusher implementation for the vector.
 */
template<SpeasyProxyParamType type>
class Pusher<type,CONTAINER_VECTOR> : public PusherBase
{
public:
	/*
	 * @brief Define some usefull types
	 */
	typedef typename MapType<type>::Type BaseElemenType;
	typedef std::vector<BaseElemenType> ElemenType;
	typedef AMDA::Parameters::ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	/*
	 * @brief Constructor
	 */
	Pusher(int dim) : PusherBase(dim, 1, CONTAINER_VECTOR, type)
	{
		_paramData = _specParamData = createParamData();
		// _nbDataByPacket = getNbDataByPacket(type, dim, 1);
	}

	/*
	 * @brief Put packet in a "vector" ParamData
	 */
	virtual int put(SpeasyProxyParamDataPacket* packet)
	{
		//ParamData is created, add data
		_specParamData->getDataList().resize(packet->getNbData());

		BaseElemenType fillEl = _fillValue;

		for (int index = 0; index < packet->getNbData(); ++index)
		{
			//get time
			double time = packet->getTime(index);

			ElemenType elem;
			for (int dimIndex = 0;  dimIndex < packet->getDim1Size(); ++dimIndex)
			{
				BaseElemenType baseElem;
				//get data element
				if (packet->getDataValue(&baseElem,index,dimIndex))
				{
				    if (!isnan(_fillValue))
					    if (baseElem == fillEl)
				        	baseElem << NotANumber();
				}
				else
					baseElem << NotANumber();
				//push data base element
				elem.push_back(baseElem);
			}

			//push time and element in the ParamData
			_specParamData->getDataList().push_back(elem);
			_specParamData->getTimeList().push_back(time);
		}

		//return nb of processed records
		return packet->getNbData();
	}

    virtual void putNaN() {
		_specParamData->getDataList().resize(1);
		ElemenType nanElem = ElemenType();
		nanElem.resize(_dim1);
		nanElem << NotANumber();
		_specParamData->getDataList().push_back(nanElem);
	}

	/*
	 * @brief ParamData creation
	 */
	SpecParamData* createParamData()
	{
		return new AMDA::Parameters::ParamDataSpec< std::vector<typename MapType<type>::Type> >(_dim1);
	}
};

/**
 * @brief Pusher implementation for the scalar.
 */
template<SpeasyProxyParamType type>
class Pusher<type,CONTAINER_SCALAR> : public PusherBase {
public:
	/*
	 * @brief Define some usefull types
	 */
	typedef typename MapType<type>::Type BaseElemenType;
	typedef BaseElemenType ElemenType;
	typedef AMDA::Parameters::ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	/*
	 * @brief Constructor
	 */
	Pusher() : PusherBase(1, 1, CONTAINER_SCALAR, type)
	{
		_paramData = _specParamData = createParamData();
		// _nbDataByPacket = getNbDataByPacket(type, 1, 1);
	}

	/*
	 * @brief Put packet in a "scalar" ParamData
	 */
	virtual int put(SpeasyProxyParamDataPacket* packet)
	{
		//ParamData is created, add data
		_specParamData->getDataList().resize(packet->getNbData());

		BaseElemenType fillEl = _fillValue;

		for (int index = 0; index < packet->getNbData(); ++index)
		{
			//get time
			double time = packet->getTime(index);

			BaseElemenType baseElem;
			//get element
			if (packet->getDataValue(&baseElem,index))
			{
				if (!isnan(_fillValue))
				{
				    if (baseElem == fillEl)
			        	baseElem << NotANumber();
				}
			}
			else
				baseElem << NotANumber();

			//push time and element in the ParamData
			_specParamData->getDataList().push_back(baseElem);
			_specParamData->getTimeList().push_back(time);
		}

		return packet->getNbData();
	}

    virtual void putNaN() {
                BaseElemenType valNaN;
                valNaN << NotANumber();
		_specParamData->getDataList().resize(1);
		_specParamData->getDataList().push_back(valNaN);
	}

	SpecParamData* createParamData() {
		return new SpecParamData();
	}
};

} /* namespace SpeasyProxyInterface */
} /* namespace AMDA */
#endif /* PUSHER_H_ */