Ignore:
Timestamp:
Jan 26, 2011, 5:08:25 PM (9 years ago)
Author:
robert@…
Message:
  • Created tests for the synchronization and trash
  • Improved synchronizationservice and trash
  • Put authorization checks in several pages
Location:
trunk/grails-app/controllers/nl/tno/metagenomics
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/nl/tno/metagenomics/AssayController.groovy

    r4 r7  
    55class AssayController {
    66        def synchronizationService
     7        def gscfService
    78        def fuzzySearchService
    89
    910        def fileService
    1011        def excelService
    11 
    12         // Fields to be edited using excel file and manually
    13         def sampleNameName = "Sample name"
    14         def tagSequenceName = "Tag sequence"
    15         def oligoNumberName = "Oligo number"
    16         def possibleFields = [sampleNameName, tagSequenceName, oligoNumberName]
    17 
     12        def sampleExcelService
     13
     14        def index = {
     15                // Filter studies for the ones the user is allowed to see
     16                def studies = Study.list();
     17                [studies: studies.findAll { it.canRead( session.user ) },
     18                        gscfAddUrl: gscfService.urlAddStudy() ]
     19        }
     20       
    1821        def show = {
    19                 // load study with id specified by param.id
    20                 def assay = Assay.get(params.id as Long)
    21 
    22                 if (!assay) {
    23                         flash.message = "No assay found with id: $params.id"
    24                         redirect('action': 'errorPage')
    25                         return
    26                 }
     22                def assay = getAssay( params.id );
     23                if( !assay )
     24                        return
    2725
    2826                // Make sure the newest data is available
     
    6159                                if( !assay ) {
    6260                                        flash.message = "No assay found with token: $params.id"
    63                                         redirect('action': 'errorPage')
     61                                        redirect(controller: 'study')
    6462                                }
    6563                        }
     
    7977         */
    8078        def downloadTagsExcel = {
    81                 def sheetIndex = 0;
    82 
    8379                // load study with id specified by param.id
    84                 def assay = Assay.get(params.id as Long)
    85 
    86                 if (!assay) {
    87                         flash.message = "No assay found with id: $params.id"
    88                         redirect('action': 'errorPage')
    89                         return
    90                 }
    91 
    92                 // Create an excel sheet
    93                 def wb = excelService.create();
    94 
    95                 // Put the headers on the first row
    96                 excelService.writeHeader( wb, possibleFields, sheetIndex );
    97 
    98                 // Adding the next lines
    99                 def sortedSamples = assay.assaySamples.toList().sort { it.sample.name }
    100                 ArrayList data = [];
    101                 sortedSamples.each { assaySample ->
    102                         data << [assaySample.sample.name, assaySample.tagSequence, assaySample.oligoNumber ];
    103                 }
    104                 excelService.writeData( wb, data, sheetIndex, 1 );
    105 
    106                 // Auto resize columns
    107                 excelService.autoSizeColumns( wb, sheetIndex, 0..2)
     80                def assay = getAssay( params.id );
     81                if( !assay )
     82                        return
     83
     84                def filename = assay.study.name + "_" + assay.name + "_tags.xls"
     85                excelService.downloadSampleExcel( assay.assaySamples );
    10886
    10987                // Make file downloadable
    110                 log.trace( "Creation for downloading the file " + assay.study.name + "_" + assay.name + "_tags.xls" )
    111                 excelService.downloadFile( wb, assay.study.name + "_" + assay.name + "_tags.xls", response)
     88                log.trace( "Creation for downloading the file " + filename )
     89                sampleExcelService.excelService.downloadFile( wb, filename, response )
    11290        }
    11391
     
    11694         */
    11795        def parseTagExcel = {
    118                 def sheetIndex = 0
    119                 def headerRow = 0
    120                 def dataStartsAtRow = 1
    121                 def numExampleRows = 5
    122 
    123                 // load study with id specified by param.id
    124                 def assay = Assay.get(params.id as Long)
    125 
    126                 if (!assay) {
    127                         flash.message = "No assay found with id: $params.id"
    128                         redirect('action': 'errorPage')
    129                         return
    130                 }
     96                def assay = getAssay( params.id );
     97                if( !assay )
     98                        return
    13199
    132100                def filename = params.filename
     
    150118                // Save the filename in session for later use
    151119                session.filename = filename;
    152 
    153                 // Create an excel workbook instance of the file
    154                 def workbook
     120                def excelData;
    155121                try {
    156                         workbook = excelService.open( file );
     122                        excelData = sampleExcelService.parseTagsExcel( file );
    157123                } catch( Throwable e ) { // Catch a throwable here instead of an exception, since the apache poi stuff gives an Error on failure
    158124                        // Couldn't create a workbook from this file.
    159125                        response.status = 400 // Bad request
    160                         render "Uploaded file is not a valid excel file."
    161                         return
    162                 }
    163 
    164                 // Read headers from the first row and 5 of the first lines as example data
    165                 def headers = excelService.readRow( workbook, sheetIndex, headerRow );
    166                 def exampleData = excelService.readData( workbook, sheetIndex, dataStartsAtRow, -1, numExampleRows ); // -1 means: determine number of rows yourself
    167 
    168                 // Try to guess best matches between the excel file and the column names
    169                 def bestMatches = [:]
    170 
    171                 headers.eachWithIndex { header, idx ->
    172                         // Do matching using fuzzy search. The 0.1 treshold makes sure that no match if chosen if
    173                         // there is actually no match at all.
    174                         bestMatches[idx] = fuzzySearchService.mostSimilar( header, possibleFields, 0.1 );
    175                 }
    176 
    177                 [assay: assay, headers: headers, exampleData: exampleData, filename: filename, possibleFields: [ "Don't import" ] + possibleFields, bestMatches: bestMatches]
     126                        render "Uploaded file is not a valid excel file: " + e.getMessage()
     127                        return
     128                }
     129                session.possibleFields = excelData.possibleFields
     130               
     131                [assay: assay, headers: excelData.headers, exampleData: excelData.exampleData, filename: filename, possibleFields: [ "Don't import" ] + excelData.possibleFields, bestMatches: excelData.bestMatches]
    178132        }
    179133
     
    182136         */
    183137        def updateTagsByExcel = {
    184                 def sheetIndex = 0
    185                 def headerRow = 0
    186                 def dataStartsAtRow = 1
    187 
    188                 // load study with id specified by param.id
    189                 def assay = Assay.get(params.id as Long)
    190 
    191                 if (!assay) {
     138                def assay = getAssay( params.id );
     139                if( !assay ) {
    192140                        // Now delete the file, since we don't need it anymore
    193141                        _deleteUploadedFileFromSession()
    194 
    195                         flash.message = "No assay found with id: $params.id"
    196                         redirect('action': 'errorPage')
    197                         return
     142                        return;
    198143                }
    199144
     
    210155                def matchColumns = params[ 'matches'];
    211156
    212                 if( !matchColumns ) {
    213                         // Now delete the file, since we don't need it anymore
    214                         _deleteUploadedFileFromSession()
    215 
    216                         flash.error = "No column matches found for excel file. Please try again."
    217                         redirect( action: 'show', id: params.id)
    218                         return
    219                 }
    220 
    221                 // Determine column numbers
    222                 def columns = [:]
    223                 def dataMatches = false;
    224                 possibleFields.each { columnName ->
    225                         columns[ columnName ] = matchColumns.findIndexOf { it.value == columnName }
    226 
    227                         if( columnName != sampleNameName && columns[ columnName ] != -1 )
    228                                 dataMatches = true
    229                 }
    230 
    231                 println( "Columns: " + columns)
    232 
    233                 // A column to match the sample name must be present
    234                 if( columns[ sampleNameName ] == -1 ) {
    235                         // Now delete the file, since we don't need it anymore
    236                         _deleteUploadedFileFromSession()
    237 
    238                         flash.error = "There must be a column present in the excel file that matches the sample name. Please try again."
    239                         redirect( action: 'show', id: params.id)
    240                         return
    241                 }
    242 
    243                 // A column with data should also be present
    244                 if( !dataMatches ) {
    245                         // Now delete the file, since we don't need it anymore
    246                         _deleteUploadedFileFromSession()
    247 
    248                         flash.error = "There are no data columns present in the excel file. No samples are updated."
    249                         redirect( action: 'show', id: params.id)
    250                         return
    251                 }
    252 
    253157                // Now loop through the excel sheet and update all samples with the specified data
    254158                File file = new File( fileService.getUploadDir(), session.filename );
     159               
    255160                if( !file.exists() || !file.canRead() ) {
    256161                        flash.error = "Excel file has been removed since previous step. Please try again."
     
    258163                        return
    259164                }
    260 
    261                 def workbook = excelService.open( file )
    262                 ArrayList data = excelService.readData( workbook, sheetIndex, dataStartsAtRow )
    263 
    264                 // Check whether the excel file contains any data
    265                 if( data.size() == 0 ) {
    266                         // Now delete the file, since we don't need it anymore
    267                         _deleteUploadedFileFromSession()
    268 
    269                         flash.error = "The excel sheet contains no data to import. Please upload another excel file."
    270                         redirect( action: 'show', id: params.id)
    271 
    272                         return
    273                 }
    274 
    275                 def numSuccesful = 0
    276                 def failedRows = []
    277 
    278                 // walk through all rows and fill the table with records
    279                 def assaySamples = assay.assaySamples
    280 
    281                 for( def i = 0; i < data.size(); i++ ) {
    282                         def rowData = data[ i ];
    283 
    284                         String sampleName = rowData[ columns[ sampleNameName ] ] as String
    285 
    286                         // Find assay by sample name. Since sample names are unique within an assay (enforced by GSCF),
    287                         // this will always work.
    288                         AssaySample assaySample = assaySamples.find { it.sample.id == Sample.findByName( sampleName )?.id };
    289 
    290                         // If no assaysample is found, add this row to the failed-row list
    291                         if( !assaySample ) {
    292                                 failedRows << [ row: rowData, sampleName: sampleName ];
    293                                 continue;
    294                         }
    295 
    296                         columns.each {
    297                                 if( it.value > -1 ) {
    298                                         switch( it.key ) {
    299                                                 case tagSequenceName:   assaySample.tagSequence = rowData[ it.value ]; break
    300                                                 case oligoNumberName:   assaySample.oligoNumber = rowData[ it.value ]; break
    301                                         }
    302                                 }
    303                         }
    304 
    305                         assaySample.save()
    306 
    307                         numSuccesful++;
    308                 }
    309 
    310                 // Now delete the file, since we don't need it anymore
    311                 _deleteUploadedFileFromSession()
     165               
     166                def excelData = sampleExcelService.updateTagsByExcel( matchColumns, session.possibleFields, file, assay.assaySamples );
    312167
    313168                // Return a message to the user
    314                 if( numSuccesful == 0 ) {
    315                         flash.error = "None of the " + failedRows.size() + " row(s) could be imported, because none of the sample names matched. Have you provided the right excel file?"
     169                if( !excelData.success ) {
     170                        flash.error = excelData.message
     171                } else if( excelData.numSuccesful == 0 ) {
     172                        flash.error = "None of the " + excelData.failedRows.size() + " row(s) could be imported, because none of the sample names matched. Have you provided the right excel file?"
    316173                } else {
    317                         flash.message = numSuccesful + " samples have been updated. "
    318 
    319                         if( failedRows.size() > 0 )
    320                                 flash.message += failedRows.size() + " row(s) could not be imported, because the sample names could not be found in the database."
    321                 }
    322                 redirect( action: 'show', id: params.id)
     174                        flash.message = excelData.numSuccesful + " samples have been updated. "
     175
     176                        if( excelData.failedRows.size() > 0 )
     177                                flash.message += excelData.failedRows.size() + " row(s) could not be imported, because the sample names could not be found in the database."
     178                }
     179                redirect( action: 'show', id: params.id )
    323180        }
    324181
     
    327184         */
    328185        def updateTagsManually = {
    329                 // load study with id specified by param.id
    330                 def assay = Assay.get(params.id as Long)
    331 
    332                 if (!assay) {
    333                         flash.message = "No assay found with id: $params.id"
    334                         redirect('action': 'errorPage')
    335                         return
    336                 }
     186                def assay = getAssay( params.id );
     187                if( !assay )
     188                        return
    337189
    338190                // Loop through all assay samples and set data
     
    342194                        assay.assaySamples.each { assaySample ->
    343195                                def assaySampleParams = sampleParams.get( assaySample.id as String );
     196                                println assaySampleParams
    344197                                if( assaySampleParams ) {
    345                                         assaySample.properties = assaySampleParams
     198                                        assaySample.oligoNumber = assaySampleParams.oligoNumber
     199                                        assaySample.tagSequence = assaySampleParams.tagSequence
     200
     201                                        try {
     202                                                assaySample.run = Run.get( assaySampleParams.run as Long );
     203                                        } catch( Exception e ) {}
     204
    346205                                        assaySample.save()
    347206                                }
     
    363222         */
    364223        def addExistingRuns = {
    365                 // load study with id specified by param.id
    366                 def assay = Assay.get(params.id as Long)
    367 
    368                 if (!assay) {
    369                         flash.message = "No assay found with id: $params.id"
    370                         redirect('action': 'errorPage')
    371                         return
    372                 }
     224                def assay = getAssay( params.id );
     225                if( !assay )
     226                        return
    373227
    374228                // Add checked runs to this assay
     
    397251         */
    398252        def removeRun = {
    399                 // load study with id specified by param.id
    400                 def assay = Assay.get(params.id as Long)
    401 
    402                 if (!assay) {
    403                         flash.message = "No assay found with id: $params.id"
    404                         redirect('action': 'errorPage')
    405                         return
    406                 }
     253                def assay = getAssay( params.id );
     254                if( !assay )
     255                        return
    407256
    408257                if( !params.run_id ) {
     
    449298                session.filename = ''
    450299        }
     300       
     301        protected Assay getAssay(def assayId) {
     302                // load study with id specified by param.id
     303                def assay
     304                try {
     305                        assay = Assay.get(assayId as Long)
     306                } catch( Exception e ) {
     307                        flash.error = "Incorrect id given: " + assayId
     308                        redirect(controller: 'study')
     309                        return null
     310                }
     311
     312                if (!assay) {
     313                        flash.error = "No assay found with id: " + assayId
     314                        redirect(controller: 'study')
     315                        return null
     316                }
     317               
     318                if (!assay.study.canRead( session.user ) ) {
     319                        flash.error = "You don't have the right authorizaton to access assay " + assay.name
     320                        redirect(controller: 'study')
     321                        return null
     322                }
     323               
     324                return assay
     325        }
     326       
    451327
    452328}
  • trunk/grails-app/controllers/nl/tno/metagenomics/AssaySampleController.groovy

    r4 r7  
    1414                }
    1515               
    16                 [assaySample: assaySample]
     16                if (!assaySample.assay.study.canRead( session.user ) ) {
     17                        flash.error = "You don't have the right authorizaton to access sample " + assaySample.sample.name
     18                        redirect(controller: 'study')
     19                        return null
     20                }
     21
     22               
     23                [assaySample: assaySample, entityType: params.entityType]
    1724        }
    1825}
  • trunk/grails-app/controllers/nl/tno/metagenomics/FastaController.groovy

    r5 r7  
    1818         */
    1919        def showProcessScreen = {
    20                 // load study with id specified by param.id
    21                 def assay = Assay.get(params.id as Long)
    22 
    23                 if (!assay) {
    24                         flash.message = "No assay found with id: $params.id"
    25                         redirect( controller: 'assay', action:  'errorPage')
    26                         return
    27                 }
     20                def entityType = params.entityType
    2821
    2922                // Check whether files are given
     
    3225                if( !names ) {
    3326                        flash.message = "No files uploaded for processing"
    34                         redirect( controller: 'assay', action: 'show', 'id': params.id)
     27                        redirect( controller: params.entityType, action: 'show', 'id': params.id)
    3528                        return
    3629                }
     
    5952                ]
    6053                       
    61                 [assay: assay, filenames: names, url: createLink( action: 'showProcessResult', id: assay.id, params: [ selectedRun: params.selectedRun ] ) ]
     54                [entityId: params.id, entityType: params.entityType, filenames: names, url: createLink( action: 'showProcessResult', id: params.id, params: [entityType: entityType] ) ]
    6255        }
    6356       
     
    6659         */
    6760        def process = {
    68                 // load study with id specified by param.id
    69                 def assay = Assay.get(params.id as Long)
    70 
    71                 if (!assay) {
    72                         response.setStatus( 404, "No assay found with id: $params.id" )
     61                def entity
     62                def assaySamples
     63               
     64                switch( params.entityType ) {
     65                        case "run":
     66                                entity = getRun( params.id );
     67                                assaySamples = entity.assaySamples;
     68                                break;
     69                        case "assay":
     70                                entity = getAssay( params.id );
     71                                assaySamples = entity.assaySamples;
     72                                break;
     73                        default:
     74                                response.setStatus( 404, "No controller found" );
     75                                render "";
     76                                return;
     77                }
     78
     79                if (!entity) {
     80                        response.setStatus( 404, flash.error )
    7381                        render "";
    7482                        return
     
    113121                        session.processProgress.bytesProcessed = bytes;
    114122                } );
     123       
     124                // Check which assaySamples to use (only the ones visible to the user)
     125                assaySamples = assaySamples.findAll { it.assay.study.canWrite( session.user ) }
    115126
    116127                // Match files with samples in the database
    117                 def matchedFiles = fastaService.matchFiles( parsedFiles.success, assay.assaySamples );
     128                def matchedFiles = fastaService.matchFiles( parsedFiles.success, assaySamples );
    118129
    119130                // Sort files on filename
     
    141152        def showProcessResult = {
    142153                // load study with id specified by param.id
    143                 def assay = Assay.get(params.id as Long)
    144 
    145                 if (!assay) {
    146                         flash.message = "No assay found with id: $params.id"
    147                         redirect( controller: 'assay', action:  'errorPage')
    148                         return
    149                 }
    150 
     154                def entity
     155               
     156                switch( params.entityType ) {
     157                        case "run":
     158                                entity = getRun( params.id )
     159                                break;
     160                        case "assay":
     161                                entity = getAssay( params.id )
     162                                break;
     163                        default:
     164                                response.setStatus( 404, "No entity found" );
     165                                render "";
     166                                return;
     167                }
     168
     169                if (!entity) {
     170                        response.setStatus( 404, flash.error )
     171                        render "";
     172                        return
     173                }
     174               
    151175                if( !session.processedFiles ) {
    152176                        flash.error = "Processing of files failed. Maybe the session timed out."
     
    155179                }
    156180               
    157                 [assay: assay, parsedFiles: session.processedFiles.parsed, matchedFiles: session.processedFiles.matched, selectedRun: params.selectedRun ]
     181                [entityType: params.entityType, entity: entity, id: params.id, parsedFiles: session.processedFiles.parsed, matchedFiles: session.processedFiles.matched, selectedRun: params.selectedRun ]
    158182        }
    159183
     
    162186         */
    163187        def saveProcessedFiles = {
    164                 // load study with id specified by param.id
    165                 def assay = Assay.get(params.id as Long)
    166 
    167                 if (!assay) {
    168                         flash.message = "No assay found with id: $params.id"
    169                         redirect( controller: 'assay', action: 'errorPage')
     188                // load entity with id specified by param.id
     189                def entity
     190               
     191                switch( params.entityType ) {
     192                        case "run":
     193                                entity = getRun( params.id );
     194                                break;
     195                        case "assay":
     196                                entity = getAssay( params.id );
     197                                break;
     198                        default:
     199                                response.setStatus( 404, "No entity found" );
     200                                render "";
     201                                return;
     202                }
     203
     204                if (!entity) {
     205                        response.setStatus( 404, flash.error )
     206                        render "";
    170207                        return
    171208                }
     
    176213                if( !files ) {
    177214                        flash.message = "No files were selected."
    178                         redirect( controller: 'assay', action: 'show', 'id': params.id)
     215                        redirect( controller: params.entityType, action: 'show', 'id': params.id)
    179216                        return
    180217                }
     
    202239                                                sd.numSequences = permanent.numSequences
    203240                                                sd.averageQuality = permanent.avgQuality
    204                                                
    205                                                 // Couple the data to the right run and sample
    206                                                 def run = Run.get( filevalue.run )
    207                                                 if( run )
    208                                                         run.addToSequenceData( sd );
    209241                                                       
    210242                                                def sample = AssaySample.get( filevalue.assaySample );
     
    251283                }
    252284               
    253                 redirect( controller: 'assay', action: "show", id: params.id )
     285                redirect( controller: params.entityType, action: "show", id: params.id )
    254286        }
    255287       
    256288        def deleteData = {
    257289                // load study with id specified by param.id
    258                 def sequenceData = SequenceData.get(params.id as Long)
     290                def sequenceData
     291               
     292                try {
     293                        sequenceData = SequenceData.get(params.id as Long)
     294                } catch( Exception e ) {}
    259295
    260296                if (!sequenceData) {
    261297                        flash.error = "No sequencedata found with id: $params.id"
    262                         redirect( controller: 'assay', action: 'errorPage')
    263                         return
    264                 }
    265 
    266                 def assayId = sequenceData.sample.assay.id;
     298                        redirect( controller: 'study' )
     299                        return
     300                }
     301
     302                def entityId
     303                def entityType
     304               
     305                switch( params.entityType ) {
     306                        case "run":
     307                                entityId = sequenceData.sample.run?.id;
     308                                entityType = "run"
     309                                break;
     310                        case "assay":
     311                        default:
     312                                entityType = "assay";
     313                                entityId = sequenceData.sample.assay.id;
     314                                break;
     315                }
     316                 
    267317                def numFiles = sequenceData.numFiles();
    268318                sequenceData.delete();
    269319
    270320                flash.message = numFiles + " file" + (numFiles != 1 ? "s have" : " has" ) + " been deleted from this sample"
    271                 redirect( controller: 'assay', action: 'show', id: assayId )
     321
     322                redirect( controller: entityType, action: 'show', id: entityId )
     323        }
     324       
     325        protected Assay getAssay(def assayId) {
     326                // load assay with id specified by param.id
     327                def assay
     328                try {
     329                        assay = Assay.get(assayId as Long)
     330                } catch( Exception e ) {
     331                        flash.error = "Incorrect id given: " + assayId
     332                        return null
     333                }
     334
     335                if (!assay) {
     336                        flash.error = "No assay found with id: " + assayId
     337                        return null
     338                }
     339               
     340                if (!assay.study.canRead( session.user ) ) {
     341                        flash.error = "You don't have the right authorizaton to access assay " + assay.name
     342                        return null
     343                }
     344               
     345                return assay
     346        }
     347       
     348        protected Run getRun(def runId) {
     349                // load run with id specified by param.id
     350                def run
     351                try {
     352                        run = Run.get(runId as Long)
     353                } catch( Exception e ) {
     354                        flash.error = "Incorrect id given: " + runId
     355                        return null
     356                }
     357
     358                if (!run) {
     359                        flash.error = "No run found with id: " + runId
     360                        return null
     361                }
     362
     363                return run
    272364        }
    273365}
  • trunk/grails-app/controllers/nl/tno/metagenomics/RunController.groovy

    r4 r7  
    77class RunController {
    88        def fileService
    9        
    10         /** 
    11          * Shows information about this run in dialog style
    12          */
     9        def synchronizationService
     10        def sampleExcelService
     11
     12        def index = {
     13                [runs: Run.list()]
     14        }
     15
    1316        def show = {
    14                 Run run = Run.get( params.id as long );
    15                 Assay assay = Assay.get( params.assayId as long );
    16                
    17                 if( !run ) {
    18                         render "Run not found";
    19                         return
    20                 }
    21                
    22                 if( !assay ) {
    23                         render "Assay not found";
    24                         return
    25                 }
    26                
     17                // load run with id specified by param.id
     18                def run = getRun( params.id );
     19
     20                if (!run) {
     21                        redirect(controller: 'study', action: 'index')
     22                        return
     23                }
     24
     25                // Make sure the newest data is available
     26                synchronizationService.sessionToken = session.sessionToken
     27                synchronizationService.synchronizeStudies();
     28
     29                // Determine runs not used in this assay
     30                def otherAssays = Assay.list( sort: "name" ).findAll { !it.runs.contains( run ) }
     31
     32                // Send the assay information to the view
     33                [run: run, otherAssays: otherAssays, editable: true]
     34        }
     35
     36        /**
     37         * Shows a form to edit the specified run in dialog mode
     38         */
     39        def editForm = {
     40                // load run with id specified by param.id
     41                Run run = getRun( params.id );
     42
     43                if (!run) {
     44                        render flash.error
     45                        return
     46                }
     47
     48                Assay assay = getAssay( params.id )
     49
     50                if( !assay ) {
     51                        render flash.error;
     52                        return
     53                }
     54
    2755                [assay: assay, run: run]
    2856        }
    29        
    30         /**
    31          * Shows a form to edit the specified run in dialog mode
    32          */
    33         def editForm = {
    34                 Run run = Run.get( params.id as long );
    35                 Assay assay = Assay.get( params.assayId as long );
    36                
    37                 if( !run ) {
    38                         render "Run not found";
    39                         return
    40                 }
    41                
    42                 if( !assay ) {
    43                         render "Assay not found";
    44                         return
    45                 }
    46                
    47                 [assay: assay, run: run]
    48         }
    49        
    50     def create = {
    51                 Assay a = Assay.get( params.id as long );
     57
     58        def create = {
     59                Assay a = getAssay(params.id);
     60                flash.error = "";
    5261
    5362                // Create run based on given parameters
    5463                Run run = new Run();
    55                
     64
    5665                run.setPropertiesFromForm( params );
    5766
    58                 a.addToRuns( run );
     67                if( a )
     68                        a.addToRuns( run );
    5969
    6070                if( !run.save() ) {
     
    6474                }
    6575
    66                 redirect( controller: "assay", action: "show", id: params.id )
    67         }
    68        
     76                if( a )
     77                        redirect( controller: "assay", action: "show", id: a.id )
     78                else
     79                        redirect( controller: 'run' );
     80        }
     81
    6982        def update = {
    7083                if( !params.assayId ) {
    7184                        flash.error = "No assay id given"
    72                         redirect(controller: 'assay', action: 'errorpage')
    73                         return
    74                 }
    75                 def assay = Assay.get(params.assayId as Long)
    76                
    77                 // load run with id specified by param.id
    78                 if (!assay) {
    79                         flash.message = "No assay found with id: ${params.assayId}"
    80                         redirect(controller: 'assay', 'action': 'errorPage')
    81                         return
    82                 }
    83 
    84 
    85                 def run
    86 
    87                 try {
    88                         run = Run.get( params.id as Long );
    89                 } catch( Exception e ) {
    90                         throw e
    91                         flash.message = "Incorrect run id given: "
     85                        redirect(controller: 'study')
     86                        return
     87                }
     88
     89                Assay assay = getAssay(params.assayId);
     90
     91                if( !a ) {
     92                        redirect( controller: 'study' );
     93                }
     94
     95                Run run = getRun( params.id );
     96
     97                if( !run ) {
    9298                        redirect(controller: 'assay', action: 'show', id: params.assayId)
    9399                        return
     
    106112                redirect( controller: 'assay', action: 'show', id: params.assayId)
    107113        }
    108        
     114
    109115        def delete = {
    110                 Run run = Run.get( params.id as long );
     116                Run run = getRun( params.id );
     117
     118                if( !run ) {
     119                        redirect(controller: 'assay', action: 'show', id: params.assayId)
     120                        return
     121                }
    111122
    112123                // Don't remove runs for which data exists
     
    115126                        redirect( controller: "assay", action: "show", id: params.assayId )
    116127                }
    117                
     128
    118129                // Remove all associations
    119130                run.assays.each {
    120131                        run.removeFromAssays( it );
    121132                }
    122                
     133
    123134                def name = run.name
    124135                run.delete();
     
    126137
    127138                redirect( controller: "assay", action: "show", id: params.assayId )
     139        }
     140
     141        /**************************************************************************
     142         *
     143         * Methods for handling data about the samples in this run
     144         *
     145         *************************************************************************/
     146
     147        /**
     148         * Downloads an excel sheet with data about the assay samples, to enter data in excel
     149         */
     150        def downloadTagsExcel = {
     151                Run run = getRun( params.id );
     152
     153                if( !run ) {
     154                        redirect(controller: 'study')
     155                        return
     156                }
     157
     158                // Make it only possible to update samples writable by the user
     159                def assaySamples = run.assaySamples.findAll { it.assay.study.canWrite( session.user ) }
     160
     161                def filename = "Run " + run.name + "_tags.xls"
     162                def wb = sampleExcelService.downloadSampleExcel( assaySamples, false );
     163
     164                // Make file downloadable
     165                log.trace( "Creation for downloading the file " + filename )
     166                sampleExcelService.excelService.downloadFile( wb, filename, response )
     167        }
     168
     169
     170        /**
     171         * Parses an uploaded excel file and shows a form to match columns
     172         */
     173        def parseTagExcel = {
     174                Run run = getRun( params.id );
     175
     176                if( !run ) {
     177                        redirect(controller: 'study')
     178                        return
     179                }
     180
     181                def filename = params.filename
     182
     183                // Security check to prevent accessing files in other directories
     184                if( !filename || filename.contains( '..' ) ) {
     185                        response.status = 500;
     186                        render "Invalid filename given";
     187                        return;
     188                }
     189
     190                // Check for existence and readability
     191                File file = new File( fileService.getUploadDir(), filename)
     192
     193                if( !file.exists() || !file.canRead() ) {
     194                        response.status = 404;
     195                        render "The uploaded file doesn't exist or doesn't work as expected.";
     196                        return;
     197                }
     198
     199                // Save the filename in session for later use
     200                session.filename = filename;
     201                def excelData;
     202                try {
     203                        excelData = sampleExcelService.parseTagsExcel( file, false );
     204                } catch( Throwable e ) { // Catch a throwable here instead of an exception, since the apache poi stuff gives an Error on failure
     205                        // Couldn't create a workbook from this file.
     206                        response.status = 400 // Bad request
     207                        render "Uploaded file is not a valid excel file: " + e.getMessage()
     208                        return
     209                }
     210                session.possibleFields = excelData.possibleFields
     211
     212                [run: run, headers: excelData.headers, exampleData: excelData.exampleData, filename: filename, possibleFields: [ "Don't import" ] + excelData.possibleFields, bestMatches: excelData.bestMatches]
     213        }
     214
     215        /**
     216         * Updates the assay samples based on the given excel file and the column matches
     217         */
     218        def updateTagsByExcel = {
     219                Run run = getRun( params.id );
     220
     221                if( !run ) {
     222                        // Now delete the file, since we don't need it anymore
     223                        _deleteUploadedFileFromSession()
     224
     225                        redirect(controller: 'study')
     226                        return
     227                }
     228
     229                if( !session.filename ) {
     230                        // Now delete the file, since we don't need it anymore
     231                        _deleteUploadedFileFromSession()
     232
     233                        flash.error = "No excel file found because session timed out. Please try again."
     234                        redirect( action: 'show', id: params.id)
     235                        return
     236                }
     237
     238                // Determine the match-columns
     239                def matchColumns = params[ 'matches'];
     240
     241                // Now loop through the excel sheet and update all samples with the specified data
     242                File file = new File( fileService.getUploadDir(), session.filename );
     243
     244                if( !file.exists() || !file.canRead() ) {
     245                        flash.error = "Excel file has been removed since previous step. Please try again."
     246                        redirect( action: 'show', id: params.id)
     247                        return
     248                }
    128249               
     250                // Make it only possible to update samples writable by the user
     251                def assaySamples = run.assaySamples.findAll { it.assay.study.canWrite( session.user ) }
     252               
     253                def excelData = sampleExcelService.updateTagsByExcel( matchColumns, session.possibleFields, file, assaySamples );
     254
     255                // Return a message to the user
     256                if( !excelData.success ) {
     257                        flash.error = excelData.message
     258                } else if( excelData.numSuccesful == 0 ) {
     259                        flash.error = "None of the " + excelData.failedRows.size() + " row(s) could be imported, because none of the sample names matched or no samples are writable. Have you provided the right excel file?"
     260                } else {
     261                        flash.message = excelData.numSuccesful + " samples have been updated. "
     262
     263                        if( excelData.failedRows.size() > 0 )
     264                                flash.message += excelData.failedRows.size() + " row(s) could not be imported, because the sample names could not be found in the database or you don't have the proper permissions to change them."
     265                }
     266                redirect( action: 'show', id: params.id )
     267        }
     268
     269
     270        /**
     271         * Update the properties of the assay samples manually
     272         */
     273        def updateTagsManually = {
     274                Run run = getRun( params.id );
     275
     276                if( !run ) {
     277                        redirect(controller: 'study')
     278                        return
     279                }
     280
     281                // Loop through all assay samples and set data
     282                def sampleParams = params.assaySample;
     283
     284                if( sampleParams ) {
     285                        run.assaySamples.each { assaySample ->
     286                                def assaySampleParams = sampleParams.get( assaySample.id as String );
     287                                if( assaySampleParams ) {
     288                                        assaySample.oligoNumber = assaySampleParams.oligoNumber
     289                                        assaySample.tagSequence = assaySampleParams.tagSequence
     290
     291                                        assaySample.save()
     292                                }
     293                        }
     294                }
     295
     296                flash.message = "Data about samples is saved."
     297                redirect( action: 'show', id: params.id )
     298        }
     299
     300        /**************************************************************************
     301         *
     302         * Methods for handling data about assays for this run
     303         *
     304         *************************************************************************/
     305
     306        /**
     307         * Adds existing assays to this run
     308         */
     309        def addAssays = {
     310                Run run = getRun( params.id );
     311
     312                if( !run ) {
     313                        redirect(controller: 'study')
     314                        return
     315                }
     316
     317                // Add checked runs to this assay
     318                def assays = params.assays
     319                if( assays instanceof String ) {
     320                        assays = [ assays ]
     321                }
     322
     323                def numAdded = 0;
     324                assays.each { assay_id ->
     325                        try {
     326                                def assay = Assay.findById( assay_id as Long )
     327                                if( run.assays == null || !run.assays.contains( assay ) ) {
     328                                        run.addToAssays( assay );
     329                                        numAdded++;
     330                                }
     331                        } catch( Exception e ) {}
     332                }
     333
     334                flash.message = numAdded + " runs are added to this assay."
     335                redirect( action: 'show', id: params.id)
     336        }
     337
     338        /**
     339         * Removes assay for this run
     340         */
     341        def removeAssay = {
     342                Run run = getRun( params.id );
     343
     344                if( !run ) {
     345                        redirect(controller: 'study')
     346                        return
     347                }
     348               
     349                if( !params.assay_id ) {
     350                        flash.message = "No assay id given"
     351                        redirect(action: 'show', id: params.id)
     352                        return
     353                }
     354
     355                def assay
     356
     357                try {
     358                        assay = Assay.findById( params.assay_id as Long )
     359                } catch( Exception e ) {
     360                        throw e
     361                        flash.message = "Incorrect assay id given: "
     362                        redirect(action: 'show', id: params.id)
     363                        return
     364                }
     365
     366                if( run.assays.contains( assay ) ) {
     367                        run.removeFromAssays( assay );
     368                        flash.message = "The assay has been removed from this run."
     369                } else {
     370                        flash.message = "The given assay was not associated with this run."
     371                }
     372
     373                redirect( action: 'show', id: params.id)
     374        }
     375
     376
     377        /**
     378         * Deletes an uploaded file for which the filename is given in the session.
     379         * @return
     380         */
     381        def _deleteUploadedFileFromSession() {
     382                if( !session.filename )
     383                        return
     384
     385                // Now delete the file, since we don't need it anymore
     386                fileService.delete( session.filename  )
     387                session.filename = ''
     388        }
     389
     390        protected Run getRun(def runId) {
     391                // load study with id specified by param.id
     392                def run
     393                try {
     394                        run = Run.get(runId as Long)
     395                } catch( Exception e ) {
     396                        flash.error = "Incorrect id given: " + runId
     397                        return null
     398                }
     399
     400                if (!run) {
     401                        flash.error = "No run found with id: " + runId
     402                        return null
     403                }
     404
     405                return run
     406        }
     407
     408        protected Assay getAssay(def assayId) {
     409                // load study with id specified by param.id
     410                def assay
     411                try {
     412                        assay = Assay.get(assayId as Long)
     413                } catch( Exception e ) {
     414                        flash.error = "Incorrect id given: " + assayId
     415                        return null
     416                }
     417
     418                if (!assay) {
     419                        flash.error = "No assay found with id: " + assayId
     420                        return null
     421                }
     422
     423                if (!assay.study.canRead( session.user ) ) {
     424                        flash.error = "You don't have the right authorizaton to access assay " + assay.name
     425                        return null
     426                }
     427
     428                return assay
    129429        }
    130430}
  • trunk/grails-app/controllers/nl/tno/metagenomics/integration/TrashController.groovy

    r4 r7  
    5353                        redirect( action: "index" );
    5454                }
    55                
     55                println "Restore To: " + restoreSample
     56                println "Original Sample: " + originalSample
    5657                trashService.restoreSample( restoreSample, originalSample );
    5758                restoreSample.sample?.delete();
Note: See TracChangeset for help on using the changeset viewer.