7#include "ImportPdsTable.h"
15#include <QScopedPointer>
18#include "EndianSwapper.h"
24#include "TableField.h"
25#include "TableRecord.h"
74 const QString &pdsTableFile,
75 const QString &pdsTableName) {
77 load(pdsLabFile, pdsTableFile, pdsTableName);
133 const QString &pdsTableFile,
134 const QString &pdsTableName) {
138 loadLabel(pdsLabFile, tempTblFile, pdsTableName);
139 if (!pdsTableFile.isEmpty()) tempTblFile = pdsTableFile;
146 tempTblFile = pdsLabFile;
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() +
"]";
163 tableFile = tableFileLowercase.
expanded();
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 ["
244 for (
int i = 0 ; i <
columns() ; i++) {
247 colnames.push_back(
name);
296 const QString &dataType) {
301 return (column != 0);
321 Table table(isisTableName, record);
326 QString msg =
"Unable to import the PDS table [" +
m_tableName
351 const QString &isisTableName) {
352 return (
importTable(colnames.split(
","), isisTableName));
374 const QString &isisTableName) {
376 for (
int i = 0 ; i < colnames.size() ; i++) {
379 QString msg =
"Unable to import the PDS table [" +
m_tableName
380 +
"] into Isis. The requested column name ["
381 + colnames[i] +
"] does not "
385 ctypes.push_back(*descr);
390 Table table(isisTableName, record);
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";
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");
486 QString msg =
"Unable to import the PDS table [" + tableName
487 +
"] from the PDS file ["
488 + pdsTableFile +
"] into Isis. "
490 +
"] is not supported. Valid values are ASCII or BINARY.";
498 while (colobj != tableDetails->
endObject()) {
499 if (colobj->isNamed(
"COLUMN")) {
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;
538 QString tempTblFile(pdsTableFile);
543 while (tfile.
GetLine(tline,
false)) {
574 cd.
m_name = colobj[
"NAME"][0];
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()) +
")";
644 ColumnTypes::iterator col =
m_coldesc.begin();
647 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
670 ColumnTypes::const_iterator col =
m_coldesc.begin();
673 if (c.toUpper() == cName.toUpper()) {
return (&(*col)); }
692 const QString &delimiter)
const {
714 const QString &delimiter)
const {
723 if ( delimiter.isEmpty() )
return (
QStringList(value));
725 return ( value.split(delimiter, Qt::SkipEmptyParts) );
731 for (
int i = 0 ; i < cdesc.
m_items ; i++) {
732 fields.push_back(value.mid(pos, cdesc.
m_itemBytes));
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());
799 return ttype.split(
"_").last();
824 if ( dtype ==
"INTEGER" ) {
827 else if ( ((dtype ==
"DOUBLE")
829 || (dtype ==
"FLOAT")) ) {
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;
926 const ColumnTypes &ctypes,
928 for (
int i = 0 ; i < ctypes.size() ; i++) {
929 extract(cols, ctypes[i], record[i]);
951 const ColumnTypes &cols,
954 for (
int i = 0 ; i <
m_rows.size() ; i++) {
959 QString msg =
"Failed to convert data in row [" +
toString((
int) i) +
"]";
967 ifstream pdsFileStream(tempTblFile.toLatin1().data(), ifstream::binary);
969 if (!pdsFileStream) {
970 IString msg =
"Unable to open file containing PDS table ["
971 + tempTblFile +
"].";
976 QScopedPointer<char, QScopedPointerArrayDeleter<char> > rowBuffer(
new char[
m_recordBytes]);
981 for (
int rowIndex = 0; rowIndex <
m_trows; rowIndex++) {
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;
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 = "
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 = "
1130 else if (dataType ==
"FLOAT"
1131 || dataType ==
"REAL"
1132 || dataType ==
"SUN_REAL"
1133 || dataType ==
"MAC_REAL"
1134 || dataType ==
"IEEE_REAL" ) {
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 = "
1150 else if (dataType ==
"PC_REAL") {
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 = "
1166 else if (dataType.contains(
"CHARACTER")
1167 || dataType.contains(
"ASCII")
1168 || dataType ==
"DATE" || dataType ==
"TIME" ) {
1174 +
"] has an unsupported DATA_TYPE ["
1193 QString msg =
"Unable to import the binary PDS table [" +
m_tableName
1194 +
"]. The column DATA_TYPE values indicate differing byte "
1214 for (
int i = 0 ; i <
columns() ; i++) {
float Float(void *buf)
Swaps a floating point value.
int Int(void *buf)
Swaps a 4 byte integer value.
double Double(void *buf)
Swaps a double precision value.
File name manipulation and expansion.
QString path() const
Returns the path of the file name.
bool fileExists() const
Returns true if the file exists; false otherwise.
QString baseName() const
Returns the name of the file without the path and without extensions.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
@ Unknown
A type of error that cannot be classified as any of the other error types.
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
@ Programmer
This error is for when a programmer made an API call that was illegal.
Adds specific functionality to C++ strings.
int ToInteger() const
Returns the object string as an integer.
IString Trim(const std::string &chars)
Removes characters from the beginning and end of the IString.
QString ToQt() const
Retuns the object string as a QString.
double ToDouble() const
Returns the floating point value the IString represents.
void init()
Initialize object variables.
ColumnDescr * findColumn(const QString &colName)
Searches internal column descriptors for a named column.
virtual bool processRow(const int &row, const QString &rowdata)
Process a freshly read PDS table line of data.
void setName(const QString &name="TABLE")
Set the name of the PDS table object.
QString name() const
Return the name of the PDS table.
QString getFormattedName(const QString &colname) const
Converts a column name to a camel-case after it has been cleansed.
int rows() const
Returns the number of rows in the table.
void loadLabel(const QString &labfile, QString &tblfile, const QString &tblname="")
Loads the contents of a PDS table label description.
const ColumnDescr & getColumnDescriptor(const int &nth) const
Retrieve a column description by index.
int m_pdsTableStart
The start byte of the PDS table data.
Table importTable(const QString &isisTableName)
Populate a Table object with the PDS table and return it.
QString m_pdsTableFile
The name of the file containing the table data.
QString getColumnValue(const QString &tline, const ColumnDescr &cdesc, const QString &delimiter="") const
Extracts a column from a QString based upon a description.
void load(const QString &pdsLabFile, const QString &pdsTabFile="", const QString &pdsTableName="TABLE")
Loads a PDS table label and (optional) data file.
void setPdsByteOrder(QString byteOrder)
Sets the byte order for BINARY PDS table files.
int m_rowBytes
The number of bytes for one PDS table row.
QString m_pdsTableType
The INTERCHANGE_FORMAT value for the table.
TableField & extract(const Columns &columns, const ColumnDescr &cdesc, TableField &field) const
Extract a TableField from a PDS column in the text row.
TableRecord makeRecord(const ColumnTypes &ctypes)
Creates a TableRecord for columns.
TableRecord extractBinary(char *rowBuffer, TableRecord &record) const
This method is used to set the field values for the given record.
int m_trows
Number rows in table according to label.
QString m_tableName
The name of the PDS table object.
int m_recordBytes
The number of bytes for one Isis table record.
ColumnTypes m_coldesc
Column descriptions.
void loadTable(const QString &tabfile)
Loads the contents of a PDS table data file.
TableField makeFieldFromBinaryTable(const ColumnDescr &cdesc)
Creates an empty TableField with the appropriate type from a binary PDS table column description.
QString m_byteOrder
The byte order of the PDS table file, if binary.
virtual ~ImportPdsTable()
Destructs the ImportPdsTable object.
bool setType(const QString &colName, const QString &dataType)
Change the datatype for a column.
QString getGenericType(const QString &ttype) const
Determine generic data type of a column.
ColumnDescr getColumnDescription(PvlObject &colobj, int nth) const
Extract a column description from a COLUMN object.
ImportPdsTable()
Default constructor.
QString getType(const QString &colName) const
Get the type associated with the specified column.
bool hasColumn(const QString &colName) const
This method determines whether the PDS table has a column with the given name.
void fillTable(Table &table, const ColumnTypes &columns, TableRecord &record) const
Fill the ISIS Table object with PDS table data.
QStringList getColumnNames(const bool &formatted=true) const
Return the names of all the columns.
QString getColumnName(const unsigned int &index=0, const bool &formatted=true) const
Returns the name of the specifed column.
TableField makeField(const ColumnDescr &cdesc)
Creates a TableField for the column type.
int columns() const
Returns the number of columns in the table.
QStringList getColumnFields(const QString &tline, const ColumnDescr &cdesc, const QString &delimiter="") const
Extracts column fields from a QString based upon a description.
QString name() const
Returns the container name.
Container for cube-like labels.
Contains Pvl Groups and Pvl Objects.
PvlObjectIterator beginObject()
Returns the index of the beginning object.
bool hasKeyword(const QString &kname, FindOptions opts) const
See if a keyword is in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within ...
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
int objects() const
Returns the number of objects.
QList< PvlObject >::iterator PvlObjectIterator
The counter for objects.
PvlObject & object(const int index)
Return the object at the specified index.
PvlObjectIterator endObject()
Returns the index of the ending object.
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
Class for storing an Isis::Table's field information.
bool isInteger() const
Determines whether the field type is Integer.
bool isDouble() const
Determines whether the field type is Double.
@ Integer
The values in the field are 4 byte integers.
@ Real
The values in the field are 4 byte reals or floats.
@ Text
The values in the field are text strings with 1 byte per character.
@ Double
The values in the field are 8 byte doubles.
int size() const
Returns the number of values stored for the field at each record.
Class for storing Table blobs information.
int Fields() const
Returns the number of fields that are currently in the record.
Provides access to sequential ASCII stream I/O.
bool GetLine(QString &line, const bool skipComments=true)
Gets next line from file.
This is free and unencumbered software released into the public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
int toInt(const QString &string)
Global function to convert from a string to an integer.
Namespace for the standard library.
int m_colnum
Column number.
int m_startByte
Starting byte of data.
int m_numBytes
Number bytes in column.
QString m_dataType
PDS table DATA_TYPE of column.
int m_itemBytes
Number bytes per item.
int m_items
Number of items in column.
QString m_name
Name of column.