7 #include "ImportPdsTable.h"
15 #include <QScopedPointer>
18 #include "EndianSwapper.h"
22 #include "PvlObject.h"
24 #include "TableField.h"
25 #include "TableRecord.h"
43 ImportPdsTable::ImportPdsTable() {
46 m_tableName =
"TABLE";
73 ImportPdsTable::ImportPdsTable(
const QString &pdsLabFile,
74 const QString &pdsTableFile,
75 const QString &pdsTableName) {
76 m_tableName = pdsTableName;
77 load(pdsLabFile, pdsTableFile, pdsTableName);
84 ImportPdsTable::~ImportPdsTable() {
89 QString ImportPdsTable::name()
const {
98 void ImportPdsTable::setName(
const QString &name) {
132 void ImportPdsTable::load(
const QString &pdsLabFile,
133 const QString &pdsTableFile,
134 const QString &pdsTableName) {
138 loadLabel(pdsLabFile, tempTblFile, pdsTableName);
139 if (!pdsTableFile.isEmpty()) tempTblFile = pdsTableFile;
146 tempTblFile = pdsLabFile;
147 m_pdsTableStart = tableStartRecord;
155 + tableFile.
name().toLower());
157 IString msg =
"Unable to import PDS table. Neither of the following "
158 "possible table files were found: ["
160 + tableFileLowercase.
expanded() +
"]";
161 throw IException(e, IException::Unknown, msg, _FILEINFO_);
163 tableFile = tableFileLowercase.
expanded();
168 if (m_pdsTableType ==
"ASCII") {
169 loadTable(tempTblFile);
171 m_pdsTableFile = tempTblFile;
186 bool ImportPdsTable::hasColumn(
const QString &colName)
const {
187 return (findColumn(colName) != 0);
211 QString ImportPdsTable::getColumnName(
const unsigned int &index,
212 const bool &formatted)
const {
213 if ((
int) index >= columns() - 1) {
214 QString msg =
"Unable to import the binary PDS table [" + m_tableName
215 +
"] into Isis. The requested column index ["
216 +
toString((
int) index) +
"] exceeds the last column index ["
218 throw IException(IException::Programmer, msg.toStdString(), _FILEINFO_);
220 QString name = m_coldesc[index].m_name;
221 if (formatted) name = getFormattedName(name);
242 QStringList ImportPdsTable::getColumnNames(
const bool &formatted)
const {
244 for (
int i = 0 ; i < columns() ; i++) {
245 QString name = m_coldesc[i].m_name;
246 if (formatted) name = getFormattedName(name);
247 colnames.push_back(name);
268 QString ImportPdsTable::getType(
const QString &colName)
const {
295 bool ImportPdsTable::setType(
const QString &colName,
296 const QString &dataType) {
301 return (column != 0);
318 Table ImportPdsTable::importTable(
const QString &isisTableName) {
321 Table table(isisTableName, record);
322 fillTable(table, m_coldesc, record);
326 QString msg =
"Unable to import the PDS table [" + m_tableName
327 +
"] from the PDS file [" + m_pdsTableFile +
"] into Isis.";
328 throw IException(e, IException::Unknown, msg.toStdString(), _FILEINFO_);
350 Table ImportPdsTable::importTable(
const QString &colnames,
351 const QString &isisTableName) {
352 return (importTable(colnames.split(
","), isisTableName));
374 const QString &isisTableName) {
376 for (
int i = 0 ; i < colnames.size() ; i++) {
377 const ColumnDescr *descr = findColumn(colnames[i]);
379 QString msg =
"Unable to import the PDS table [" + m_tableName
380 +
"] into Isis. The requested column name ["
381 + colnames[i] +
"] does not "
383 throw IException(IException::Programmer, msg.toStdString(), _FILEINFO_);
385 ctypes.push_back(*descr);
390 Table table(isisTableName, record);
391 fillTable(table, ctypes, record);
401 void ImportPdsTable::init() {
438 void ImportPdsTable::loadLabel(
const QString &pdsLabFile,
439 QString &pdsTableFile,
440 const QString &tblname) {
444 QString tableName = ( tblname.isEmpty() ) ? m_tableName : tblname;
446 QString msg =
"The PDS file " + pdsLabFile +
447 " does not have the required TABLE object, ["
448 + tableName +
"]. The PDS label file is probably invalid";
449 throw IException(IException::Unknown, msg.toStdString(), _FILEINFO_);
455 m_recordBytes = (int) tabObj.
findKeyword(
"RECORD_BYTES");
460 m_recordBytes = (int) tabObj.
findKeyword(
"ROW_BYTES") +
466 m_recordBytes = (int) label.
findKeyword(
"RECORD_BYTES");
469 QString trueTableName;
472 trueTableName = tableName;
474 + label[
"^" + tableName][0];
476 else if (tabObj.
objects() == 1) {
478 tableDetails = &tabObj.
object(0);
480 + tabObj[
"^" + trueTableName][0];
483 int ncols = (int) tableDetails->
findKeyword(
"COLUMNS");
484 m_pdsTableType = QString(tableDetails->
findKeyword(
"INTERCHANGE_FORMAT"));
485 if (m_pdsTableType !=
"ASCII" && m_pdsTableType.toUpper() !=
"BINARY") {
486 QString msg =
"Unable to import the PDS table [" + tableName
487 +
"] from the PDS file ["
488 + pdsTableFile +
"] into Isis. "
489 "The PDS INTERCHANGE_FORMAT [" + m_pdsTableType
490 +
"] is not supported. Valid values are ASCII or BINARY.";
491 throw IException(IException::User, msg.toStdString(), _FILEINFO_);
493 m_rowBytes = tableDetails->
findKeyword(
"ROW_BYTES");
498 while (colobj != tableDetails->
endObject()) {
499 if (colobj->isNamed(
"COLUMN")) {
500 m_coldesc.push_back(getColumnDescription(*colobj, icol));
507 if (ncols != columns()) {
509 msg <<
"Number of columns in the COLUMNS label keyword (" << ncols
510 <<
") does not match number of COLUMN objects found ("
512 cout << msg.str() << endl;
534 void ImportPdsTable::loadTable(
const QString &pdsTableFile) {
538 QString tempTblFile(pdsTableFile);
543 while (tfile.
GetLine(tline,
false)) {
544 if (irow >= m_trows)
break;
546 (void) processRow(irow, tline);
572 ImportPdsTable::getColumnDescription(
PvlObject &colobj,
int nth)
const {
574 cd.
m_name = colobj[
"NAME"][0];
577 if (m_pdsTableType ==
"ASCII") {
578 cd.
m_dataType = getGenericType(colobj[
"DATA_TYPE"][0]).toUpper();
581 cd.
m_dataType = colobj[
"DATA_TYPE"][0].toUpper();
595 cd.
m_items = (int) colobj[
"ITEMS"];
617 if ( (nth >= columns()) || ( nth < 0) ) {
618 QString mess =
"Index (" + QString::number(nth) +
619 ") into Columns invalid (max: " + QString::number(columns()) +
")";
620 throw IException(IException::Programmer, mess, _FILEINFO_);
624 return (m_coldesc[nth]);
643 QString cName = getFormattedName(colName);
644 ColumnTypes::iterator col = m_coldesc.begin();
645 while (col != m_coldesc.end()) {
646 QString c = getFormattedName(col->m_name);
647 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
669 QString cName = getFormattedName(colName);
670 ColumnTypes::const_iterator col = m_coldesc.begin();
671 while (col != m_coldesc.end()) {
672 QString c = getFormattedName(col->m_name);
673 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
690 QString ImportPdsTable::getColumnValue(
const QString &tline,
692 const QString &delimiter)
const {
714 const QString &delimiter)
const {
717 QString value = getColumnValue(tline, cdesc, delimiter);
723 if ( delimiter.isEmpty() )
return (
QStringList(value));
725 return ( value.split(delimiter, QString::SkipEmptyParts) );
731 for (
int i = 0 ; i < cdesc.
m_items ; i++) {
732 fields.push_back(value.mid(pos, cdesc.
m_itemBytes));
759 QString ImportPdsTable::getFormattedName(
const QString &colname)
const {
760 QString cname = QString(colname).replace(QRegExp(
"[(),]"),
" ").simplified();
762 bool uppercase =
true;
764 for (
int i = 0 ; i < cname.size() ; i++) {
766 oString.push_back(cname[i].toUpper());
769 else if ( (cname[i] ==
' ') || (cname[i] ==
'_') ) {
773 oString.push_back(cname[i].toLower());
798 QString ImportPdsTable::getGenericType(
const QString &ttype)
const {
799 return ttype.split(
"_").last();
822 QString name = getFormattedName(cdesc.
m_name);
823 if (m_pdsTableType ==
"ASCII") {
824 if ( dtype ==
"INTEGER" ) {
825 return (
TableField(name, TableField::Integer));
827 else if ( ((dtype ==
"DOUBLE")
829 || (dtype ==
"FLOAT")) ) {
830 return (
TableField(name, TableField::Double));
837 return makeFieldFromBinaryTable(cdesc);
858 for (
int i = 0 ; i < ctypes.size() ; i++) {
889 data.
Trim(
" \t\r\n");
893 data.
Trim(
" \t\r\n");
897 QString str(tfield.
size(),
' ');
898 str.insert(0, data.
Trim(
" \t\r\n").
ToQt());
903 QString msg =
"Conversion failure of column " + cdesc.
m_name;
904 throw IException(e, IException::Programmer, msg, _FILEINFO_);
928 for (
int i = 0 ; i < ctypes.size() ; i++) {
929 extract(cols, ctypes[i], record[i]);
950 void ImportPdsTable::fillTable(
Table &table,
953 if (m_pdsTableType ==
"ASCII") {
954 for (
int i = 0 ; i < m_rows.size() ; i++) {
956 table += extract(m_rows[i], cols, record);
959 QString msg =
"Failed to convert data in row [" +
toString((
int) i) +
"]";
960 throw IException(e, IException::Programmer, msg, _FILEINFO_);
966 QString tempTblFile = m_pdsTableFile;
967 ifstream pdsFileStream(tempTblFile.toLatin1().data(), ifstream::binary);
969 if (!pdsFileStream) {
970 IString msg =
"Unable to open file containing PDS table ["
971 + tempTblFile +
"].";
972 throw IException(IException::Unknown, msg, _FILEINFO_);
976 QScopedPointer<char, QScopedPointerArrayDeleter<char> > rowBuffer(
new char[m_recordBytes]);
977 for (
int i = 1; i < m_pdsTableStart; i++) {
978 pdsFileStream.read(rowBuffer.data(), m_recordBytes);
981 for (
int rowIndex = 0; rowIndex < m_trows; rowIndex++) {
982 pdsFileStream.read(rowBuffer.data(), m_recordBytes);
983 TableRecord rec = extractBinary(rowBuffer.data(), record);
999 int ImportPdsTable::columns()
const {
1000 return (m_coldesc.size());
1011 int ImportPdsTable::rows()
const {
1012 return (m_rows.size());
1033 for (
int colIndex = 0; colIndex < columns(); colIndex++) {
1034 QString columnName = m_coldesc[colIndex].m_name;
1035 for (
int fieldIndex = 0 ; fieldIndex < record.
Fields() ; fieldIndex++) {
1036 QString fieldName = record[fieldIndex].name();
1037 if (fieldName == columnName) {
1038 int startByte = m_coldesc[colIndex].m_startByte;
1039 int numBytes = m_coldesc[colIndex].m_numBytes;
1041 if (record[fieldIndex].isInteger()) {
1043 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1045 int fieldValue = endianSwap.
Int(&columnValue);
1046 record[fieldIndex] = fieldValue;
1049 else if (record[fieldIndex].isDouble()) {
1052 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1053 double fieldValue = endianSwap.
Double(&columnValue);
1054 record[fieldIndex] = fieldValue;
1057 else if (record[fieldIndex].isReal()) {
1060 memmove(&columnValue, &rowBuffer[startByte], numBytes);
1061 float fieldValue = endianSwap.
Float(&columnValue);
1062 record[fieldIndex] = fieldValue;
1065 else if (record[fieldIndex].isText()) {
1066 QString fieldValue(numBytes,
'\0');
1067 for (
int byte = 0;
byte < numBytes;
byte++) {
1068 fieldValue[byte] = rowBuffer[startByte + byte];
1070 record[fieldIndex] = fieldValue;
1105 QString name = cdesc.
m_name;
1106 if (dataType ==
"MSB_INTEGER" || dataType ==
"INTEGER"
1107 || dataType ==
"SUN_INTEGER" || dataType ==
"MAC_INTEGER") {
1109 QString msg =
"Only 4 byte integer values are supported in Isis. "
1110 "PDS Column [" + cdesc.
m_name
1111 +
"] has an integer DATA_TYPE with [BYTES = "
1113 throw IException(IException::Unknown, msg, _FILEINFO_);
1115 setPdsByteOrder(
"MSB");
1116 return TableField(name, TableField::Integer);
1118 else if (dataType ==
"LSB_INTEGER" || dataType ==
"VAX_INTEGER"
1119 || dataType ==
"PC_INTEGER" ) {
1121 QString msg =
"Only 4 byte integer values are supported in Isis. "
1122 "PDS Column [" + cdesc.
m_name
1123 +
"] has an integer DATA_TYPE with [BYTES = "
1125 throw IException(IException::Unknown, msg, _FILEINFO_);
1127 setPdsByteOrder(
"LSB");
1128 return TableField(name, TableField::Integer);
1130 else if (dataType ==
"FLOAT"
1131 || dataType ==
"REAL"
1132 || dataType ==
"SUN_REAL"
1133 || dataType ==
"MAC_REAL"
1134 || dataType ==
"IEEE_REAL" ) {
1135 setPdsByteOrder(
"MSB");
1143 IString msg =
"Only 4 byte or 8 byte real values are supported in Isis. "
1144 "PDS Column [" + cdesc.
m_name
1145 +
"] has a real DATA_TYPE with [BYTES = "
1147 throw IException(IException::Unknown, msg, _FILEINFO_);
1150 else if (dataType ==
"PC_REAL") {
1151 setPdsByteOrder(
"LSB");
1159 QString msg =
"Only 4 byte or 8 byte real values are supported in Isis. "
1160 "PDS Column [" + cdesc.
m_name
1161 +
"] has a real DATA_TYPE with [BYTES = "
1163 throw IException(IException::Unknown, msg, _FILEINFO_);
1166 else if (dataType.contains(
"CHARACTER")
1167 || dataType.contains(
"ASCII")
1168 || dataType ==
"DATE" || dataType ==
"TIME" ) {
1174 +
"] has an unsupported DATA_TYPE ["
1176 throw IException(IException::Unknown, msg, _FILEINFO_);
1191 void ImportPdsTable::setPdsByteOrder(QString byteOrder) {
1192 if (!m_byteOrder.isEmpty() && m_byteOrder != byteOrder) {
1193 QString msg =
"Unable to import the binary PDS table [" + m_tableName
1194 +
"]. The column DATA_TYPE values indicate differing byte "
1196 throw IException(IException::Unknown, msg.toStdString(), _FILEINFO_);
1198 m_byteOrder = byteOrder;
1212 bool ImportPdsTable::processRow(
const int &row,
const QString &rowdata) {
1214 for (
int i = 0 ; i < columns() ; i++) {
1215 cols.push_back(getColumnValue(rowdata, m_coldesc[i]));
1217 m_rows.append(cols);