VOTableReader.cc 6.99 KB
/*
 * VOTableReader.cc
 *
 *  Created on: 7 août 2013
 *      Author: CS
 */

#include "VOTableData.hh"
#include "VOTableReader.hh"
#include "TimeTableCatalogUtil.hh"
#include "Catalog.hh"
#include <iostream>
#include <string.h>

namespace TimeTableCatalog {

const std::string VOTableReader::FORMAT = "VO";

VOTableReader::VOTableReader(const std::string& pPath) :
		XMLReader(pPath) {
	_tmpIntervalstartdate 	= -1;
	_mainDescriptionRead 	= false;
	_ttDescriptionRead 		= false;

	_readingDescription = false;
	_readingField 		= false;
	_readingTr			= false;
	_readingTd			= false;
	_tdCount			= 0;
}

VOTableReader::~VOTableReader() {
}

// ---------------- PUBLIC -------------------

std::unique_ptr<AbstractReader> VOTableReader::createInstance(
		const std::string& pPath) {
	return std::unique_ptr < AbstractReader > (new VOTableReader(pPath));
}

std::string VOTableReader::getFirstNode() {
	return VOTableData::VOTABLE_TAG;
}

// ----------------- PRIVATE --------------------------

/**
 *
 * @pTT : the timetable to load
 * @reader: the xmlReader
 *
 * Fills the given TimeTable with the xml file content
 */
void VOTableReader::processNode(TimeTable& pTT, xmlTextReaderPtr reader, int &crtIndex) {
	const xmlChar *name;

	// -- read tag
	name = xmlTextReaderConstName(reader);
	if (name == NULL)
		name = BAD_CAST "--";

	// get tag name to easily handle it
	std::string tagName = reinterpret_cast<const char*>(name);

	if (tagName == VOTableData::DESCRIPTION_TAG) {
		_readingDescription = !_readingDescription;
	}
	else if (tagName == VOTableData::FIELD_TAG) {
		_readingField = !_readingField;

		if (_readingField) {
			readField (pTT, reader);
		}
	}
	else if (tagName == VOTableData::TR_TAG) {
		_readingTr = !_readingTr;

		// Reset td count for each tr end
		if (_readingTr == false)
			_tdCount = 0;
	}
	else if (tagName == VOTableData::TD_TAG) {
		_readingTd = !_readingTd;
	}
	else if (tagName == "#text") {
		if (_readingDescription == true) {
			readDescription (pTT, reader);
		}
		if (_readingTr == true) {
			readInterval (pTT, reader, crtIndex);
			++crtIndex;
			_tdCount++;
		}
	}
}

void VOTableReader::readDescription(TimeTable& pTT, xmlTextReaderPtr reader) {
	// -- read tag text (may be NULL)
	const xmlChar *value = xmlTextReaderConstValue(reader);

	std::string tagValue = reinterpret_cast<const char*>(value);

	if (_mainDescriptionRead == false) {
		readMetadata(tagValue, pTT);
		_mainDescriptionRead = true;
	} else if (_ttDescriptionRead == false) {
		if (value != NULL)
			split(tagValue, '\n', pTT._description);
		else
			pTT._description.clear();
		_ttDescriptionRead = true;
	} else {
		ParameterDescription *pd = pTT.getLastParameterDescritption();
		pd->setDescription(tagValue);
	}
}

void VOTableReader::readField(TimeTable& pTT, xmlTextReaderPtr reader) {
	const xmlChar *attrName;

	attrName = xmlTextReaderGetAttribute (reader, (const xmlChar*)VOTableData::FIELD_NAME_ATTRIB.c_str());

	// Jump startTime & stopTime tag
	if ((strcmp ((char *) attrName, "startTime") != 0) &&
		(strcmp ((char *) attrName, "stopTime") != 0)){

		const xmlChar *attrId, *attrSize, *attrType, *attrUnit, *attrUcd, *attrUtype;

		attrId	 		= xmlTextReaderGetAttribute (reader, (const xmlChar*)VOTableData::FIELD_ID_ATTRIB.c_str());
		attrSize 		= xmlTextReaderGetAttribute (reader, (const xmlChar*)VOTableData::FIELD_ARRAYSIZE_ATTRIB.c_str());
		attrType 		= xmlTextReaderGetAttribute (reader, (const xmlChar*)VOTableData::FIELD_DATATYPE_ATTRIB.c_str());
		attrUnit		= xmlTextReaderGetAttribute (reader, (const xmlChar*)VOTableData::FIELD_UNIT_ATTRIB.c_str());
		attrUcd			= xmlTextReaderGetAttribute (reader, (const xmlChar*)VOTableData::FIELD_UCD_ATTRIB.c_str());
		attrUtype		= xmlTextReaderGetAttribute (reader, (const xmlChar*)VOTableData::FIELD_UTYPE_ATTRIB.c_str());

		ParameterDescription::ParameterType internalType;
		std::string voType = std::string((const char *)attrType);

		if (voType == "char") {
			internalType = ParameterDescription::ParameterType::String;
		} else if (voType == "int") {
			internalType = ParameterDescription::ParameterType::Integer;
		} else if (voType == "double") {
			internalType = ParameterDescription::ParameterType::Double;
		} else  {
			internalType = ParameterDescription::ParameterType::Unknown;
		}

		std::string internalSize("1");
		if (((char *) attrSize) != NULL) {
			internalSize = std::string((const char *)attrSize);
		}

		((Catalog *) &pTT)->addParameterDescription(ParameterDescription(
				std::string((const char *)attrId),
				std::string((const char *)attrName),
				internalSize,
				internalType,
				std::string((const char *)attrUnit),
				"",		// Read later
				std::string((const char *)attrUcd),
				std::string((const char *)attrUtype)));

	}
}

void VOTableReader::readInterval (TimeTable& pTT, xmlTextReaderPtr reader, int pcrtIndex) {
	// -- read tag text (may be NULL)
	const xmlChar *value = xmlTextReaderConstValue(reader);

	std::string tagValue = reinterpret_cast<const char*>(value);

	// first TD is startdate
	if (_tdCount == 0) {
		// read start date of interval
		_tmpIntervalstartdate = readISOTime(tagValue);

		// read time format, the first date of the first interval
		if (pTT._timeFormat == TimeTable::TIME_FORMAT::UNKNOWN) {
			pTT._timeFormat = getTimeFormat(tagValue);
		}
	} else if (_tdCount == 1) {
		// start date is set, that means we are waiting for stop date
		pTT.addInterval( TimeInterval(_tmpIntervalstartdate, readISOTime(tagValue), pcrtIndex));
	} else {
		TimeInterval * pLastInterval = pTT.getLastInterval();
		// If interval list is not empty, add parameter data to the last interval
		if (pLastInterval != NULL) {
			ParameterDescriptionList pdl = pTT.getParameterDescritptions();

			std::vector<std::string> paramList;
			split (tagValue, VOTableData::SEPARATOR.c_str()[0], paramList);

			int nbParamDataInterval = pLastInterval->getParameterDataCount();
			std::string paramKey = pdl [nbParamDataInterval].getId();
			pLastInterval->addParameterData(paramKey, paramList);
		}
	}
}

void VOTableReader::readMetadata(const std::string& pDescription,
		TimeTable& pTimeTable) {
	// try to find string like "Prop:xxxx" and set _prop attribute to "xxxx"
	std::vector<std::string> lines;
	split(pDescription, ';', lines);

	for (std::string line : lines) {

		// -- here try to find "Name:"
		if (contains(line, VOTableData::NAME_TAG)) {
			extractvalue(line, pTimeTable._name);
		}
		// -- here try to find "Historic:"
		else if (contains(line, VOTableData::HISTORIC_TAG)) {
			extractvalue(line, pTimeTable._history);
		}
		// -- here try to find "CreationDate:"
		// and try to set it as unix time
		// if impossible, add the line to the description
		else if (contains(line, VOTableData::CREATION_DATE_TAG)) {
			// convert creation date string to char*
			std::string creationDate;
			extractvalue(line, creationDate);
			// try to read date
			try {
				pTimeTable._creationDate = TimeTableCatalog::readISOTime(creationDate);
			} catch (...) {
				LOG4CXX_WARN(_logger,
						"Unable to parse creation date in " + getPath());
			}
		} else {
			// ignore lines
		}
	}
}

} /* namespace TimeTableCatalog */