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;
 
  145      int tableStartRecord = 
toInt(tableFile.baseName());
 
  146      tempTblFile = pdsLabFile;
 
  152      if (!tableFile.fileExists()) {
 
  154        FileName tableFileLowercase(tableFile.path() + 
"/" 
  155                                    + tableFile.name().toLower());
 
  156        if (!tableFileLowercase.fileExists()) {
 
  157          IString msg = 
"Unable to import PDS table.  Neither of the following " 
  158                        "possible table files were found: [" 
  159                        + tableFile.expanded() + 
"]  or [" 
  160                        + tableFileLowercase.expanded() + 
"]";
 
  163        tableFile = tableFileLowercase.expanded();
 
  164        tempTblFile = tableFile.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";
 
  454    if (tabObj.hasKeyword(
"RECORD_BYTES")) {
 
  459    else if (tabObj.hasKeyword(
"ROW_BYTES") && tabObj.hasKeyword(
"ROW_SUFFIX_BYTES")) {
 
  461                      (int) tabObj.findKeyword(
"ROW_SUFFIX_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];
 
  482    m_trows = (int) tableDetails->findKeyword(
"ROWS");
 
  483    int ncols =  (int) tableDetails->findKeyword(
"COLUMNS");
 
  484    m_pdsTableType = QString(tableDetails->findKeyword(
"INTERCHANGE_FORMAT"));
 
  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.";
 
  493    m_rowBytes = tableDetails->findKeyword(
"ROW_BYTES");
 
  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();
 
  584    cd.m_startByte = ((int) colobj[
"START_BYTE"]) - 1;   
 
  585    cd.m_numBytes = (int) colobj[
"BYTES"];
 
  588    cd.m_itemBytes = cd.m_numBytes;
 
  589    if ( colobj.hasKeyword(
"ITEM_BYTES") ) {
 
  590      cd.m_itemBytes = (int) colobj[
"ITEM_BYTES"];
 
  594    if ( colobj.hasKeyword(
"ITEMS") ) {
 
  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 {
 
  693    return (tline.mid(cdesc.m_startByte, cdesc.m_numBytes));
 
 
  714                                              const QString &delimiter)
 const {
 
  718    if ( 1 == cdesc.m_items) 
return ( 
QStringList(value) );
 
  722    if ( 0 == cdesc.m_itemBytes ) {
 
  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));
 
  733      pos += cdesc.m_itemBytes + 1;
 
 
  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();
 
 
  821    QString dtype = cdesc.m_dataType;
 
  824      if ( dtype == 
"INTEGER" ) {
 
  827      else if ( ((dtype == 
"DOUBLE")
 
  829              || (dtype == 
"FLOAT")) ) {
 
 
  858    for (
int i = 0 ; i < ctypes.size() ; i++) {
 
 
  885    int ith = cdesc.m_colnum;
 
  888      if (tfield.isInteger()) {
 
  889        data.
Trim(
" \t\r\n");
 
  892      else if (tfield.isDouble()) {
 
  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;
 
 
  928    for (
int i = 0 ; i < ctypes.size() ; i++) {
 
  929      extract(cols, ctypes[i], record[i]);
 
 
  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;
 
 
 1103    QString dataType = cdesc.m_dataType;
 
 1105    QString 
name = cdesc.m_name;
 
 1106    if (dataType == 
"MSB_INTEGER" || dataType == 
"INTEGER" 
 1107        || dataType == 
"SUN_INTEGER" || dataType == 
"MAC_INTEGER") {
 
 1108      if (cdesc.m_numBytes != 4) {
 
 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 = " 
 1112                      + 
toString(cdesc.m_numBytes) + 
"].";
 
 1118    else if (dataType == 
"LSB_INTEGER" || dataType == 
"VAX_INTEGER" 
 1119             || dataType == 
"PC_INTEGER" ) {
 
 1120      if (cdesc.m_numBytes != 4) {
 
 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 = " 
 1124                      + 
toString(cdesc.m_numBytes) + 
"].";
 
 1130    else if (dataType == 
"FLOAT"     
 1131             || dataType == 
"REAL"      
 1132             || dataType == 
"SUN_REAL"  
 1133             || dataType == 
"MAC_REAL"  
 1134             || dataType == 
"IEEE_REAL" ) {
 
 1136      if (cdesc.m_numBytes == 8) {
 
 1139      else if (cdesc.m_numBytes == 4) {
 
 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 = " 
 1146                      + 
toString(cdesc.m_numBytes) + 
"].";
 
 1150    else if (dataType == 
"PC_REAL") {
 
 1152      if (cdesc.m_numBytes == 8) {
 
 1155      else if (cdesc.m_numBytes == 4) {
 
 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 = " 
 1162                      + 
toString(cdesc.m_numBytes) + 
"].";
 
 1166    else if (dataType.contains(
"CHARACTER")
 
 1167             || dataType.contains(
"ASCII")
 
 1168             || dataType == 
"DATE" || dataType == 
"TIME" ) {
 
 1173    IString msg = 
"PDS Column [" + cdesc.m_name
 
 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++) {
 
 
File name manipulation and expansion.
 
QString path() const
Returns the path of the file name.
 
@ 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.
 
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.
 
QList< PvlObject >::iterator PvlObjectIterator
The counter for objects.
 
PvlObject & object(const int index)
Return the object at the specified index.
 
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.
 
@ 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.
 
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.
 
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.
 
QString m_dataType
PDS table DATA_TYPE of column.
 
QString m_name
Name of column.