#include "ExportManager.h" #include #include "../Common/Toolbox.h" #include "../Common/TREPS_kernel_config.h" #include "../File/FileLoaderManager.h" #include "../File/FileWriterManager.h" #include "../Transformation/TransformationRequest.h" #include "../Transformation/TransformationResult.h" #include "../TimeManager/TimeManager.h" //9639 #include using namespace TREPS::Common; using namespace TREPS::File; using namespace TREPS::Transformation; using namespace TREPS::TimeManager; namespace TREPS { namespace Export { ExportManagerClass::ExportManagerClass(void) : app(NULL), loader(NULL) { this->app = ApplicationClass::getInstance(); this->srcInfo.fields.clear(); this->srcInfo.frames.clear(); this->srcInfo.vectors.clear(); this->resInfo.fields.clear(); this->resInfo.frames.clear(); this->resInfo.vectors.clear(); this->srcData.clear(); this->resData.clear(); this->expData.clear(); this->expFields.clear(); } ExportManagerClass::~ExportManagerClass(void) { this->srcData.clear(); this->resData.clear(); this->expData.clear(); if (this->loader != NULL) { this->loader->close(); delete this->loader; this->loader = NULL; } } bool ExportManagerClass::init(const char *export_path) { //init xml file loader if (this->loader == NULL) this->loader = new XMLManagerClass(); this->loader->close(); if (!this->loader->isExist(export_path)) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Cannot find exports file : " << export_path); return false; } //load file if (!this->loader->loadFile(export_path)) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Cannot load exports file : " << export_path); return false; } //check file with xsd if (!this->loader->isValid(TREPS_EXPORTS_XSD)) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Invalid exports file : " << export_path); return false; } return true; } t_ExportStructure ExportManagerClass::getExportStructureFromId(const char *export_id) { if (strcmp(export_id,"only-res-vec") == 0) return ES_ONLYRES; else if (strcmp(export_id,"res-in-src-struct") == 0) return ES_SRCSTRUCT; else if (strcmp(export_id,"res-and-src") == 0) return ES_SRCANDRES; return ES_NONE; } bool ExportManagerClass::runExportOp(t_ExportStructure fileStruct, t_FileFormat expFileFormat, t_TimeFormat expTimeFormat, const char *expTimePattern, const char *requestPath, const char *srcPath, const char *resPath, const char *expPath) { //load information about transformation request TransformationRequestClass *transRequest = new TransformationRequestClass(); // 9639 this->transformationRequest = transRequest; if (!transRequest->loadFromFile(requestPath)) { delete transRequest; LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Cannot load information about transformation request"); return false; } //load result file this->resData.clear(); if (!this->loadFileData(resPath, this->resInfo, &this->resData)) { delete transRequest; LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to load result file " << resPath); return false; } //no transformation when srcFrame == dstFrame bool noTrans = (transRequest->getSrcFrame().compare(transRequest->getDstFrame()) == 0); //force file structure if no transformation defined t_ExportStructure realFileStruct = ES_SRCSTRUCT; if (!noTrans) realFileStruct = fileStruct; //check if the size of source vector list is the same than the result vector list if (!noTrans && (this->resInfo.vectors.size() != transRequest->getSrcVectors()->size())) { delete transRequest; this->resData.clear(); LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Number of source vectors != number of result vectors"); return false; } //Load result time field if (transRequest->getTimeFormat() != TF_NONE) this->resData.loadTimes(RESULT_TIME_ID, TF_PATTERN, RESULT_TIME_PATTERN); //load source data this->srcData.clear(); if (realFileStruct != ES_ONLYRES) { if (!this->loadFileData(srcPath, this->srcInfo, &this->srcData)) { delete transRequest; this->resData.clear(); LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to load source file " << srcPath); return false; } //load source time field if (transRequest->getTimeFormat() != TF_NONE) this->srcData.loadTimes(transRequest->getTimeFieldId().c_str(), transRequest->getTimeFormat(), transRequest->getTimePattern().c_str()); } //init data list to export this->expData.clear(); DataRecordClass *crtRecord = this->resData.getFirstRecord(); while (crtRecord != NULL) { DataRecordClass *newRecord = this->expData.addNew(); if (expTimeFormat != TF_NONE) newRecord->setTime(crtRecord->getTime()); newRecord->setTag(crtRecord->getTag()); crtRecord = crtRecord->getNextRecord(); } //init fields to export this->expFields.clear(); bool res = false; switch (realFileStruct) { case ES_ONLYRES : res = this->makeVectorsToExport(transRequest->getSrcVectors(), &this->resInfo.vectors, true, transRequest->getSrcFrame().c_str(), transRequest->getDstFrame().c_str()); break; case ES_SRCANDRES : res = this->makeVectorsToExport(transRequest->getSrcVectors(), &this->resInfo.vectors, false, transRequest->getSrcFrame().c_str(), transRequest->getDstFrame().c_str()); break; case ES_SRCSTRUCT : res = this->makeSameStructureToExport(transRequest->getSrcVectors(), &this->srcInfo.fields, &this->resInfo.vectors, transRequest->getTimeFieldId().c_str(), transRequest->getDstFrame().c_str()); break; default : res = false; } //clear source and result data this->resData.clear(); this->srcData.clear(); if (res) { map generalAttributes = this->srcInfo.attributes; res = this->writeExportedFile(expPath, expFileFormat, expTimeFormat, expTimePattern, generalAttributes); } //clear export data this->expData.clear(); this->expFields.clear(); delete transRequest; return res; } bool ExportManagerClass::makeVectorsToExport(const t_VectorList *srcVectors, const t_VectorList *resVectors, bool onlyRes, const char *srcFrame, const char *dstFrame) { for (t_VectorList::const_iterator it = srcVectors->begin(); it != srcVectors->end(); ++it) { const t_Vector *crtSrcVec = &(*it); const t_Vector *crtResVec = NULL; for (t_VectorList::const_iterator resit = resVectors->begin(); resit != resVectors->end(); ++resit) { if (crtSrcVec->id.compare((*resit).id) == 0) { crtResVec = &(*resit); break; } } if (crtResVec == NULL) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Cannot retrieve result vector for " << crtSrcVec->id); return false; } if (!onlyRes) { //generate source field id string srcFieldId = crtSrcVec->id; srcFieldId += "_"; srcFieldId += srcFrame; //create source vector field t_Field srcField = this->initNewFieldVector(srcFieldId.c_str(), srcFieldId.c_str(), FT_DOUBLE, srcFrame); //merge data if (!this->addFieldVector(&srcField, &(this->srcData), crtSrcVec->fieldId[0].c_str(), crtSrcVec->fieldId[1].c_str(), crtSrcVec->fieldId[2].c_str(), &this->expFields, &(this->expData))) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to add source field " << srcField.id); return false; } } //generate result field id string resFieldId = crtResVec->id; resFieldId += "_"; resFieldId += dstFrame; //create result vector field t_Field resField = this->initNewFieldVector(resFieldId.c_str(), resFieldId.c_str(), FT_DOUBLE, dstFrame); //merge data if (!this->addFieldVector(&resField, &(this->resData), crtResVec->fieldId[0].c_str(), crtResVec->fieldId[1].c_str(), crtResVec->fieldId[2].c_str(), &this->expFields, &(this->expData))) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to add result field " << resField.id); return false; } } return true; } bool ExportManagerClass::fieldIdAlreadyExist(const t_FieldList *fields, const char *fieldId) { for (t_FieldList::const_iterator field = fields->begin(); field != fields->end(); ++field) { if ((*field).id.compare(fieldId) == 0) return true; } return false; } bool ExportManagerClass::makeSameStructureToExport(const t_VectorList *srcVectors, const t_FieldList *srcFields, const t_VectorList *resVectors, const char *srcTimeFieldId, const char *dstFrame) { //copy source data in export data this->srcData.clone(&this->expData); // 9639 if « pattern - TF_PATTERN - user defined pattern » // update starting index copy, escape all time fields string startingIdxToCopy = ""; if(this->transformationRequest->getTimeFormat()==TF_PATTERN){ // in case "t_TimeFormat pattern 1" // count how many time field [] string lPattern = this->transformationRequest->getTimePattern(); int lCnt = std::count(lPattern.begin(), lPattern.end(), ']') - 1; std::ostringstream ostr; //output string stream ostr << lCnt; // startingIdxToCopy = std::to_string(lCnt); C++11 startingIdxToCopy = ostr.str(); //C++03 srcTimeFieldId = startingIdxToCopy.c_str(); } //copy source fields in export data (except source time field) this->expFields.clear(); for (t_FieldList::const_iterator srcField = srcFields->begin(); srcField != srcFields->end(); ++srcField) { // 9639 update starting index copy, escape all time fields //if (/*((*srcField).type == FT_TIME) &&*/ ((*srcField).id.compare(srcTimeFieldId) == 0)) //if (/*((*srcField).type == FT_TIME) &&*/ ( stoi((*srcField).id) <= stoi(srcTimeFieldId) )) //C++11 if (/*((*srcField).type == FT_TIME) &&*/ ( atoi((*srcField).id.c_str()) <= atoi(srcTimeFieldId) )) //C++03 continue; this->expFields.push_back((*srcField)); } //add result vectors if some source vectors has been defined if (!srcVectors->empty()) { for (t_VectorList::const_iterator resVec = resVectors->begin(); resVec != resVectors->end(); ++resVec) { t_Vector crtResVec = (*resVec); string resFieldId = crtResVec.id; resFieldId += "_"; resFieldId += dstFrame; t_Field resField = this->initNewFieldVector(resFieldId.c_str(), resFieldId.c_str(), FT_DOUBLE, dstFrame); if (!this->addFieldVector(&resField, &(this->resData), crtResVec.fieldId[0].c_str(), crtResVec.fieldId[1].c_str(), crtResVec.fieldId[2].c_str(), &this->expFields, &(this->expData))) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to add result field " << resField.id); return false; } } } return true; } bool ExportManagerClass::writeExportedFile(const char *expPath, t_FileFormat expFileFormat, t_TimeFormat expTimeFormat, const char *expTimePattern, map &generalAttributes) { //write the exported file FileWriterManagerClass *writerMgr = new FileWriterManagerClass(); this->addGeneralAttributes(generalAttributes); bool res = writerMgr->saveData(expPath, expFileFormat, &this->expData, expTimeFormat, expTimePattern, &this->expFields, &generalAttributes); if (!res) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to save exported file " << expPath); } delete writerMgr; return res; } t_Field ExportManagerClass::initNewFieldVector(const char *id, const char *name, t_FieldType type, const char *frame) { t_StringList frameTags = this->app->getConf()->getFramesTags(); string frameTag; if (frameTags.empty()) frameTag = EXPORT_FIELD_DEFAULTFRAME_TAG; else frameTag = (*frameTags.begin()); t_Dimension dim; dim.id = "treps_vector_dim"; dim.size = 3; t_Field field; field.id = id; field.name = name; field.dims.clear(); field.dims.push_back(dim); field.type = type; field.attributes.clear(); field.attributes[EXPORT_FIELD_DESCRIPTION_TAG] = EXPORT_FIELD_DESCRIPTION; field.attributes[frameTag] = frame; return field; } bool ExportManagerClass::addFieldVector(t_Field *field, const DataRecordListClass *data, const char *comp_1, const char *comp_2, const char *comp_3, t_FieldList *expFields, DataRecordListClass *expData) { if (field->dims.size() != 1) return false; if ((*field->dims.begin()).size != 3) return false; //field id already exist? if (this->fieldIdAlreadyExist(expFields,field->id.c_str())) { //if field id already exist, try to find a new one int index = 0; bool idOk = false; while (!idOk) { string newId = field->id; newId += "_"; newId += intToStr(index); idOk = (!this->fieldIdAlreadyExist(expFields,newId.c_str())); if (idOk) field->id = newId; } } expFields->push_back(*field); map keyMap; string key; key = field->id; key += "_TREPSID0"; keyMap[comp_1] = key; key = field->id; key += "_TREPSID1"; keyMap[comp_2] = key; key = field->id; key += "_TREPSID2"; keyMap[comp_3] = key; expData->mergeRecordList(data,keyMap); return true; } bool ExportManagerClass::loadFileData(const char *filePath, t_FileInfo &fileInfo, DataRecordListClass *fileData) { fileData->clear(); fileInfo.fields.clear(); //init file loader manager to load data FileLoaderManagerClass *fileLoaderMgr = new FileLoaderManagerClass(); if (!fileLoaderMgr->init(filePath)) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to init file loader for " << filePath); delete fileLoaderMgr; return false; } //load file info if (!fileLoaderMgr->getInfo(fileInfo)) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to get file info of " << filePath); delete fileLoaderMgr; return false; } //load file data int total = 0; if (!fileLoaderMgr->getData(0,0,fileData,total)) { LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Error to get file data of " << filePath); delete fileLoaderMgr; return false; } delete fileLoaderMgr; return true; } void ExportManagerClass::addGeneralAttributes(map &attributes) { //get ccurrent date TimeManagerClass *timeMgr = TimeManagerClass::getInstance(); timeMgr->setCurrentPattern(EXPORT_GENERAL_DATE_PATTERN); t_Time crtTime; timeMgr->from_TIMESTAMP(getCrtTime(),crtTime); //Add general attributes attributes[EXPORT_GENERAL_DESCRIPTION_TAG] = EXPORT_GENERAL_DESCRIPTION; attributes[EXPORT_GENERAL_VERSION_TAG] = TREPS_KERNEL_VERSION; attributes[EXPORT_GENERAL_DATE_TAG] = timeMgr->to_PATTERN(crtTime); } } }