VirtualInstrument.cc 10.4 KB
/*
 * VirtualInstrument.cc
 *
 *  Created on: Nov 21, 2014
 *      Author: AKKA
 */

#include "DicError.hh"

#include "LocalFileInterfaceConfig.hh"
#include "VirtualInstrument.hh"
#include "VirtualInstrumentManager.hh"
#include "VirtualInstrumentInterval.hh"

#include "LocalParamData.hh"
#include "FileReaderCDF.hh"
#include "FileReaderASCII.hh"
#include "FileReaderVOTable.hh"

#include <boost/filesystem/path.hpp>
#include <boost/filesystem.hpp>


namespace AMDA {
namespace LocalFileInterface {

VirtualInstrument::VirtualInstrument(VirtualInstrumentManager& pVirtualInstrumentManager, const std::string& VIId) :
		_virtualInstrumentManager(pVirtualInstrumentManager),
		_VIId(VIId), _globalStartTime(0.), _globalStopTime(0.),
		_filesFormat(VIFileFormat::FORMAT_UNKNOWN), _timeId(""), _fileReaderPtr(NULL)
{
}

VirtualInstrument::~VirtualInstrument()
{
	//delete the file reader if needed
	if (_fileReaderPtr != NULL)
		delete _fileReaderPtr;
}

void VirtualInstrument::addFileDefinition(const char* pName, double pStart,double pStop)
{
	//push back a file in the files list
	LocalFileDefinition newDef;

	newDef._name  = pName;
	newDef._start = pStart;
	newDef._stop  = pStop;

	_files.push_back(newDef);
}

bool VirtualInstrument::createFileReader(void)
{
	if (_fileReaderPtr != NULL)
		//file reader already created
		return true;

	switch (_filesFormat)
	{
	case VIFileFormat::FORMAT_CDF :
		//CDF file format
		_fileReaderPtr = new FileReaderCDF();
		LOG4CXX_INFO(gLogger, "VirtualInstrument::createFileReader - CDF Reader created");
		break;
	case VIFileFormat::FORMAT_ASCII :
		//ASCII file format
		_fileReaderPtr = new FileReaderASCII();
		LOG4CXX_INFO(gLogger, "VirtualInstrument::createFileReader - ASCII Reader created");
		break;
	case VIFileFormat::FORMAT_VOT :
		//VOTable file format
		_fileReaderPtr = new FileReaderVOTable();
		LOG4CXX_INFO(gLogger, "VirtualInstrument::createFileReader - VOTable Reader created");
		break;
	default:
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createFileReader - Reader not implemented");
	}

	return (_fileReaderPtr != NULL);
}

std::string VirtualInstrument::getFileFullPath(int fileIndex)
{
	//build file full path from file index
	if ((fileIndex >= (int)_files.size()) || (fileIndex < 0))
		return "";

	std::string filePath = _virtualInstrumentManager.getBasePath()+"/";
	filePath += _files[fileIndex]._name;
	boost::filesystem::path p(filePath);
	boost::filesystem::path full_p = boost::filesystem::complete(p); // complete == absolute

	std::string res = full_p.string();

	return res;
}

PusherBase* VirtualInstrument::createPusher(std::string& paramId,
		LocalParamType &paramType, int& dim1Size, int& dim2Size)
{
	LOG4CXX_DEBUG(gLogger, "VirtualInstrument::createPusher " << paramId);

	PusherBase* lPusher = NULL;

	//Check reader
	if (_fileReaderPtr == NULL)
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - No reader defined");
		return NULL;
	}

	//Check list of files
	if (_files.empty())
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - No file define for the VirtualInstrument " << _VIId);
		return NULL;
	}

	//use the first file to get the param type
	std::string filePath = getFileFullPath(0);

	//open the file
	if (!_fileReaderPtr->open(filePath))
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Cannot open file " << filePath);
		return NULL;
	}

	//get param type and size
	bool success = _fileReaderPtr->getParamInfo(paramId, paramType, dim1Size, dim2Size);

	//close the file
	if (!_fileReaderPtr->close())
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Cannot close file " << filePath);
	}

	if (!success)
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Cannot get param info for " << paramId);
		return NULL;
	}

	if (paramType == LocalParamType::TYPE_UNKNOWN)
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Unknown data type");
		return NULL;
	}

	//create the pusher
	if ((dim1Size > 1) && (dim2Size > 1))
	{
		//Tab2D
		switch (paramType)
		{
		case TYPE_FLOAT :
			lPusher = new Pusher<TYPE_FLOAT,LocalContainerType::CONTAINER_MATRIX>(dim1Size,dim2Size);
			break;
		case TYPE_DOUBLE :
			lPusher = new Pusher<TYPE_DOUBLE,LocalContainerType::CONTAINER_MATRIX>(dim1Size,dim2Size);
			break;
		case TYPE_SHORT :
			lPusher = new Pusher<TYPE_SHORT,LocalContainerType::CONTAINER_MATRIX>(dim1Size,dim2Size);
			break;
		case TYPE_INT :
			lPusher = new Pusher<TYPE_INT,LocalContainerType::CONTAINER_MATRIX>(dim1Size,dim2Size);
			break;
		default:
			lPusher = NULL;
			LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Data type not implemented");
		}
	}
	else if ((dim1Size > 1) || (dim2Size > 1))
	{
		//vector
		int dimSize = (dim1Size > 1) ? dim1Size : dim2Size;
		switch (paramType)
		{
		case TYPE_FLOAT :
			lPusher = new Pusher<TYPE_FLOAT,LocalContainerType::CONTAINER_VECTOR>(dimSize);
			break;
		case TYPE_DOUBLE :
			lPusher = new Pusher<TYPE_DOUBLE,LocalContainerType::CONTAINER_VECTOR>(dimSize);
			break;
		case TYPE_SHORT :
			lPusher = new Pusher<TYPE_SHORT,LocalContainerType::CONTAINER_VECTOR>(dimSize);
			break;
		case TYPE_INT :
			lPusher = new Pusher<TYPE_INT,LocalContainerType::CONTAINER_VECTOR>(dimSize);
			break;
		default:
			lPusher = NULL;
			LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Data type not implemented");
		}
	}
	else if (dim1Size == 1)
	{
		//scalar
		switch (paramType)
		{
		case TYPE_FLOAT :
			lPusher = new Pusher<TYPE_FLOAT,LocalContainerType::CONTAINER_SCALAR>();
			break;
		case TYPE_DOUBLE :
			lPusher = new Pusher<TYPE_DOUBLE,LocalContainerType::CONTAINER_SCALAR>();
			break;
		case TYPE_SHORT :
			lPusher = new Pusher<TYPE_SHORT,LocalContainerType::CONTAINER_SCALAR>();
			break;
		case TYPE_INT :
			lPusher = new Pusher<TYPE_INT,LocalContainerType::CONTAINER_SCALAR>();
			break;
		default:
			lPusher = NULL;
			LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Data type not implemented");
		}
	}
	else {
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Incorrect param size");
		return NULL;
	}

	return lPusher;
}

bool VirtualInstrument::updateTimeId()
{
	LOG4CXX_DEBUG(gLogger, "VirtualInstrument::updateTimeId");

	//Check reader
	if (_fileReaderPtr == NULL)
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::updateTimeId - No reader defined");
		return false;
	}

	//Check list of files
	if (_files.empty())
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::updateTimeId - No file define for the VirtualInstrument " << _VIId);
		return false;
	}

	//use the first file to get the time param id
	std::string filePath = getFileFullPath(0);

	//open the file
	if (!_fileReaderPtr->open(filePath))
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::updateTimeId - Cannot open file " << filePath);
		return false;
	}

	_timeId = _fileReaderPtr->getTimeParamId();

	LOG4CXX_DEBUG(gLogger, "VirtualInstrument::updateTimeId - _timeId: " << _timeId);

	//close the file
	if (!_fileReaderPtr->close())
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::updateTimeId - Cannot close file " << filePath);
	}

	return (_timeId != "");
}

ParamFlowSPtr VirtualInstrument::getParamFlow(const std::string& pParamId, TimeIntervalListSPtr pTimeIntervalList,
		LocalParamType paramType, int dim1Size, int dim2Size)
{
	// Define function to compare two TimeIntervalListSptr.
	// This used to identify if the requested TimeIntervalList already exist in _intervalList attribute or not.
	auto lIt = std::find_if( _intervalList.begin(), _intervalList.end(), [&](const IntervalList::value_type& val) -> bool {
		if (val.first->size() != pTimeIntervalList->size()) {
			return false;
		} else {
			TimeIntervalList::const_iterator itA = val.first->begin();
			TimeIntervalList::const_iterator itB = pTimeIntervalList->begin();
			while (itA != val.first->end()) {
				if ( (itA->_startTime != itB->_startTime) || (itA->_stopTime != itB->_stopTime) ) {
					return false;
				} else {
					++itA;
					++itB;
				}
			}
			return true;
		}
	});

	// TimeIntervalListSPtr not found
	if (lIt == _intervalList.end()) {
		std::pair<TimeIntervalListSPtr, VirtualIntrumentIntervalSPtr> value(pTimeIntervalList, VirtualIntrumentIntervalSPtr(new VirtualInstrumentInterval(*this, pTimeIntervalList.get())));
		std::pair<IntervalList::iterator,bool> lIter = _intervalList.insert(value);
		lIt = lIter.first;
	} else {
		// Nothing to do.
	}

	return lIt->second->getParamFlow(pParamId, paramType, dim1Size, dim2Size);
}

bool VirtualInstrument::getDataPosition(double &time, int& fileIndex, int& recordIndex)
{
	LOG4CXX_DEBUG(gLogger, "VirtualInstrument::getDataPosition");

	if (time > _globalStopTime)
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::getDataPosition - Time out of the global interval definition");
		return false;
	}

	//Check if time is include in a file
	fileIndex = 0;
	for (auto fileInfo : _files)
	{
		if ((fileInfo._start <= time) && (fileInfo._stop >= time))
			break;
		++fileIndex;
	}

	if (fileIndex == (int)_files.size())
	{
		//change time to the nearest file start time
		fileIndex = 0;
		for (auto fileInfo : _files)
		{
			if (fileInfo._start > time)
			{
				time = fileInfo._start;
				recordIndex = 0;
				return true;
			}
			++fileIndex;
		}
	}

	//search time position in file
	std::string filePath = getFileFullPath(fileIndex);

	//open the file
	if (!_fileReaderPtr->open(filePath))
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::getDataPosition - Cannot open file " << filePath);
		return false;
	}

	recordIndex = _fileReaderPtr->getRecordIndex(_timeId, time);

	//close the file
	if (!_fileReaderPtr->close())
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::createPusher - Cannot close file " << filePath);
	}

	return (recordIndex >= 0);
}

FileReaderStatus VirtualInstrument::getParamPacketData(std::string& paramId, int fileIndex, int recordIndex,
		double stopTime, LocalParamDataPacket *packet)
{
	LOG4CXX_DEBUG(gLogger, "VirtualInstrument::getParamPacketData");
	if (fileIndex >= (int)_files.size())
		//no more file available
		return FRS_FINISH;

	//get file full path
	std::string filePath = getFileFullPath(fileIndex);

	if (filePath == "")
		return FRS_ERROR;

	//open the file
	if (!_fileReaderPtr->open(filePath))
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::getParamData - Cannot open file " << filePath);
		return FRS_ERROR;
	}

	FileReaderStatus status = _fileReaderPtr->getParamPacketData(_timeId, paramId, recordIndex,
			stopTime, packet);

	//close the file
	if (!_fileReaderPtr->close())
	{
		LOG4CXX_ERROR(gLogger, "VirtualInstrument::getParamData - Cannot close file " << filePath);
	}

	return status;
}

} /* namespace LocalFileInterface */
} /* namespace AMDA */