Beispiel #1
0
TableNode* addNewDeclTable(char isparam, TableNode* symbol, Node* ast,Table* table) {
    TableNode* temp;
    listID* aux;
    checkIfExists(ast->id->id,table);
    temp = (TableNode*) calloc(sizeof(TableNode),1);
    assert(temp != NULL);
    symbol->next    = temp;
    symbol          = temp;
    symbol->n_type  = TABLE_DECL;
    symbol->type    = ast->type;
    symbol->id      = ast->id;
    symbol->isParam = isparam;

    //If more than a id has been if() declared in the same line
    if(symbol->id->next != NULL) {
        aux = symbol->id->next;
        while(aux != NULL) {
            checkIfExists(aux->id,table);
            temp = (TableNode*) calloc(sizeof(TableNode),1);
            assert(temp!=NULL);

            symbol->next   = temp;
            symbol         = temp;
            symbol->n_type = TABLE_DECL;
            symbol->type   = ast->type;
            symbol->id     = aux;
            aux            = aux->next;
        }
    }
    return temp;
}
Beispiel #2
0
Table* createSymbols(Node* ast) {

    Table* mainTable = NULL;
    Table* currentTable = NULL;
    Table* tempTable = NULL;
    TableNode* temp = NULL;
    TableNode * symbol = NULL;
    TableNode* auxiliar = NULL;
    Node* aux;

    if(ast != NULL && ast->n_type == NODE_PROGRAM) {
        if(mainTable == NULL){
            //Create the table
            mainTable = (Table*) calloc(sizeof(Table),1);
            assert(mainTable != NULL);

            //Create the TableNode and add it to the table
            temp = (TableNode*) calloc(sizeof(TableNode),1);
            assert(temp != NULL);

            temp->n_type     = TABLE_CLASS;
            temp->id         = ast->id;
            mainTable->table = temp;
            currentTable     = mainTable;
            symbol           = temp;
        }
        else {
            assert(mainTable != NULL);
        }
        ast = ast->next;
    }
    while(ast != NULL) {
        if( ast->n_type == NODE_VARDECL) {
            symbol = addNewDeclTable(0, symbol,ast, mainTable);
            ast    = ast->next;
        }
        else if( ast->n_type == NODE_METHODDECL) {
            //Create a local table
            tempTable = (Table*) calloc(sizeof(Table),1);
            assert(tempTable!=NULL);

            //Link it to the old table
            currentTable->next = tempTable;
            currentTable = tempTable;
            checkIfExists(ast->id->id,mainTable);

            //Add the MethodDecl to the old table (it must be the mainTable??)
            temp = (TableNode*) calloc(sizeof(TableNode),1);
            assert(temp!=NULL);

            symbol->next   = temp;
            symbol         = temp;
            symbol->n_type = TABLE_METHOD;
            symbol->type   = ast->type;
            symbol->id     = ast->id;
            auxiliar       = temp;

            //Create the first and the second symbol of the new table
            temp = (TableNode*) calloc(sizeof(TableNode),1);
            assert(temp!=NULL);
            currentTable->table = temp;
            symbol              = temp;
            symbol->n_type      = TABLE_METHOD;
            symbol->type        = ast->type;
            symbol->id          = ast->id;

            //add the params of the method to the method decl
            if(ast->n1->n1 != NULL) {
                aux = ast->n1->n1;
                while(aux != NULL) {
                    symbol = addNewDeclTable(1,symbol,aux, currentTable);
                    aux    = aux->next;
               }
            }
            //Add the decls of the method to the method decl
            if(ast->n2->n1!=NULL) {
                aux = ast->n2->n1;
                while(aux != NULL) {
                    symbol = addNewDeclTable(0,symbol,aux, currentTable);
                    aux    = aux->next;
                }
            }
            symbol = auxiliar;
            ast    = ast->next;
        }
    }
    return mainTable;
}
void medAbstractDatabaseImporter::importFile ( void )
{
    QMutexLocker locker ( &d->mutex );

    /* The idea of this algorithm can be summarized in 3 steps:
     * 1. Get a list of all the files that will (try to) be imported or indexed
     * 2. Filter files that cannot be read, or won't be possible to write afterwards, or are already in the db
     * 3. Fill files metadata, write them to the db, and populate db tables
     *
     * note that depending on the input files, they might be aggregated by volume
     */

    // 1) Obtain a list of all the files that are going to be processed
    // this flattens the tree structure (if the input is a directory)
    // and puts all the files in one single list
    QStringList fileList = getAllFilesToBeProcessed ( d->file );

    // Files that pass the filters named above are grouped
    // by volume in this map and will be written in the db after.
    // the key will be the name of the aggregated file with the volume
    QMap<QString, QStringList> imagesGroupedByVolume;
    QMap<QString, QString> imagesGroupedByPatient;
    QMap<QString, QString> imagesGroupedBySeriesId;

    int currentFileNumber = 0; // this variable will be used only for calculating progress

    // if importing, and depending on the input files, they might be aggregated
    // that is: files corresponding to the same volume will be written
    // in a single output meta file (e.g. .mha)
    // this map is used to store a unique id per volume and its volume number
    QMap<QString, int> volumeUniqueIdToVolumeNumber;
    int volumeNumber = 1;

    // 2) Select (by filtering) files to be imported
    //
    // In this first loop we read the headers of all the images to be imported
    // and check if we don't have any problem in reading the file, the header
    // or in selecting a proper format to store the new file afterwards
    // new files ARE NOT written in medInria database yet, but are stored in a map for writing in a posterior step

    QString tmpPatientId;
    QString currentPatientId = "";
    QString patientID;

    QString tmpSeriesUid;
    QString currentSeriesUid = "-1";
    QString currentSeriesId = "";

    bool atLeastOneImportSucceeded = false;

    foreach ( QString file, fileList )
    {
        if ( d->isCancelled ) // check if user cancelled the process
            break;

        emit progress ( this, ( ( qreal ) currentFileNumber/ ( qreal ) fileList.count() ) * 50.0 ); //TODO: reading and filtering represents 50% of the importing process?

        currentFileNumber++;

        QFileInfo fileInfo ( file );
        if (fileInfo.size() != 0)
        {
            dtkSmartPointer<medAbstractData> medData;

            // 2.1) Try reading file information, just the header not the whole file

            bool readOnlyImageInformation = true;
            medData = tryReadImages ( QStringList ( fileInfo.filePath() ), readOnlyImageInformation );

            if ( !medData )
            {
                qWarning() << "Reader was unable to read: " << fileInfo.filePath();
                continue;
            }

            // 2.2) Fill missing metadata
            populateMissingMetadata ( medData, medMetaDataKeys::SeriesID.getFirstValue(medData));
            QString patientName = medMetaDataKeys::PatientName.getFirstValue(medData).simplified();
            QString birthDate = medMetaDataKeys::BirthDate.getFirstValue(medData);
            tmpPatientId = patientName + birthDate;

            if(tmpPatientId != currentPatientId)
            {
                currentPatientId = tmpPatientId;

                patientID = getPatientID(patientName, birthDate);
            }

            medData->setMetaData ( medMetaDataKeys::PatientID.key(), QStringList() << patientID );

            tmpSeriesUid = medMetaDataKeys::SeriesDicomID.getFirstValue(medData);

            if (tmpSeriesUid != currentSeriesUid)
            {
                currentSeriesUid = tmpSeriesUid;
                currentSeriesId = medMetaDataKeys::SeriesID.getFirstValue(medData);
            }
            else
                medData->setMetaData ( medMetaDataKeys::SeriesID.key(), QStringList() << currentSeriesId );

            // 2.3) Generate an unique id for each volume
            // all images of the same volume should share the same id
            QString volumeId = generateUniqueVolumeId ( medData );

            // check whether the image belongs to a new volume
            if ( !volumeUniqueIdToVolumeNumber.contains ( volumeId ) )
            {
                volumeUniqueIdToVolumeNumber[volumeId] = volumeNumber;
                volumeNumber++;
            }

            // 2.3) a) Determine future file name and path based on patient/study/series/image
            // i.e.: where we will write the imported image
            QString imageFileName = determineFutureImageFileName ( medData, volumeUniqueIdToVolumeNumber[volumeId] );
#ifdef Q_OS_WIN32
            if ( (medStorage::dataLocation() + "/" + imageFileName).length() > 255 )
            {
                emit showError ( tr ( "Your database path is too long" ), 5000 );
                emit dataImported(medDataIndex(), d->uuid);
                emit failure ( this );
                return;
            }
#endif
            // 2.3) b) Find the proper extension according to the type of the data
            // i.e.: in which format we will write the file in our database
            QString futureExtension  = determineFutureImageExtensionByDataType ( medData );

            // we care whether we can write the image or not if we are importing
            if (!d->indexWithoutImporting && futureExtension.isEmpty()) {
                emit showError(tr("Could not save file due to unhandled data type: ") + medData->identifier(), 5000);
                continue;
            }

            imageFileName = imageFileName + futureExtension;

            // 2.3) c) Add the image to a map for writing them all in medInria's database in a posterior step

            // First check if patient/study/series/image path already exists in the database
            // Should we emit a message otherwise ??? TO
            if ( !checkIfExists ( medData, fileInfo.fileName() ) )
            {
                imagesGroupedByVolume[imageFileName] << fileInfo.filePath();
                imagesGroupedByPatient[imageFileName] = patientID;
                imagesGroupedBySeriesId[imageFileName] = currentSeriesId;
            }
        }
        else
        {
            QString error = QString(tr("Could not read empty file: ") + fileInfo.completeBaseName());
            qWarning() << __FUNCTION__ << error;
            emit showError(error, 5000);
        }
    }

    // some checks to see if the user cancelled or something failed
    if ( d->isCancelled )
    {
        emit showError (tr ( "User cancelled import process" ), 5000 );
        emit dataImported(medDataIndex(), d->uuid);
        emit cancelled ( this );
        return;
    }

    // from now on the process cannot be cancelled
    emit disableCancel ( this );

    // 3) Re-read selected files and re-populate them with missing metadata
    //    then write them to medInria db and populate db tables

    QMap<QString, QStringList>::const_iterator it = imagesGroupedByVolume.begin();
    QMap<QString, QString>::const_iterator  itPat = imagesGroupedByPatient.begin();
    QMap<QString, QString>::const_iterator  itSer = imagesGroupedBySeriesId.begin();

    // 3.1) first check is after the filtering we have something to import
    // maybe we had problems with all the files, or they were already in the database
    if ( it == imagesGroupedByVolume.end() )
    {
        // TODO we know if it's either one or the other error, we can make this error better...
        emit showError (tr ( "No compatible image found or all of them had been already imported." ), 5000 );
        emit dataImported(medDataIndex(), d->uuid);
        emit failure ( this );
        return;
    }
    else
        qDebug() << "Chosen directory contains " << imagesGroupedByVolume.size() << " files";

    int imagesCount = imagesGroupedByVolume.count(); // used only to calculate progress
    int currentImageIndex = 0; // used only to calculate progress

    medDataIndex index; //stores the last volume's index to be emitted on success

    // final loop: re-read, re-populate and write to db
    for ( ; it != imagesGroupedByVolume.end(); it++ )
    {
        emit progress ( this, ( ( qreal ) currentImageIndex/ ( qreal ) imagesCount ) * 50.0 + 50.0 ); // 50? I do not think that reading all the headers is half the job...

        currentImageIndex++;

        QString aggregatedFileName = it.key(); // note that this file might be aggregating more than one input files
        QStringList filesPaths = it.value();   // input files being aggregated, might be only one or many
        patientID = itPat.value();
        QString seriesID = itSer.value();

        //qDebug() << currentImageIndex << ": " << aggregatedFileName << "with " << filesPaths.size() << " files";

        dtkSmartPointer<medAbstractData> imagemedData;

        QFileInfo imagefileInfo ( filesPaths[0] );

        // 3.2) Try to read the whole image, not just the header
        bool readOnlyImageInformation = false;
        imagemedData = tryReadImages ( filesPaths, readOnlyImageInformation );

        if ( imagemedData )
        {
            // 3.3) a) re-populate missing metadata
            // if there is no SeriesDescription, we use the tag Series Instance UID (specific and required)
            populateMissingMetadata ( imagemedData, medMetaDataKeys::SeriesDicomID.getFirstValue(imagemedData));
            imagemedData->setMetaData ( medMetaDataKeys::PatientID.key(), QStringList() << patientID );
            imagemedData->setMetaData ( medMetaDataKeys::SeriesID.key(), QStringList() << seriesID );

            // 3.3) b) now we are able to add some more metadata
            addAdditionalMetaData ( imagemedData, aggregatedFileName, filesPaths );
        }
        else
        {
            qWarning() << "Could not repopulate data!";
            emit showError (tr ( "Could not read data: " ) + filesPaths[0], 5000 );
            emit dataImported(medDataIndex(), d->uuid);
            emit failure(this);
            return;
        }

        if ( !d->indexWithoutImporting )
        {
            // create location to store file
            QFileInfo fileInfo ( medStorage::dataLocation() + aggregatedFileName );
            if ( !fileInfo.dir().exists() && !medStorage::mkpath ( fileInfo.dir().path() ) )
            {
                qDebug() << "Cannot create directory: " << fileInfo.dir().path();
                continue;
            }

            // now writing file
            bool writeSuccess = tryWriteImage ( fileInfo.filePath(), imagemedData );

            if ( !writeSuccess )
            {
                emit showError (tr ( "Could not save data file: " ) + filesPaths[0], 5000 );
                continue;
            }
        }
        atLeastOneImportSucceeded = true;

        // and finally we populate the database
        QFileInfo aggregatedFileNameFileInfo ( aggregatedFileName );
        QString pathToStoreThumbnails = aggregatedFileNameFileInfo.dir().path() + "/" + aggregatedFileNameFileInfo.completeBaseName() + "/";
        index = this->populateDatabaseAndGenerateThumbnails ( imagemedData, pathToStoreThumbnails );
        
        if(!d->uuid.isNull())
        {
            emit dataImported(index, d->uuid);
        }
        else
        {
            emit dataImported(index);
        }

        itPat++;
        itSer++;
    } // end of the final loop

    if ( ! atLeastOneImportSucceeded) {
        emit progress ( this,100 );
        emit dataImported(medDataIndex(), d->uuid);
        emit failure(this);
        return;
    }

    d->index = index;
    
    emit progress ( this,100 );
    emit success ( this );
}