Changeset 63
- Timestamp:
- Jun 8, 2011, 4:08:49 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 20 added
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/conf/BaseFilters.groovy
r53 r63 121 121 if( !authentication.authenticated ) { 122 122 log.info "Not authenticated: " + authentication.authenticated 123 redirect( url: gscfService.urlAuthRemote(params, session.sessionToken) ) 123 if( request.method == "GET" ) { 124 redirect( url: gscfService.urlAuthRemote(params, session.sessionToken) ) 125 } else { 126 log.debug "POST request: redirect can't be handled properly"; 127 flash.message = "Unfortunately, your request could not be completed, because the system had to log you in first. Please try again." 128 129 redirect( url: gscfService.urlAuthRemote(null, session.sessionToken) ) 130 } 124 131 return false 125 132 } … … 149 156 session.sessionToken = "${UUID.randomUUID()}" 150 157 log.info("SessionToken created, redirecting to GSCF to let the user login! (SessionToken: ${session.sessionToken})") 151 152 redirect( url: gscfService.urlAuthRemote(params, session.sessionToken) ) 158 159 if( request.method == "GET" ) { 160 redirect( url: gscfService.urlAuthRemote(params, session.sessionToken) ) 161 } else { 162 log.debug "POST request: redirect can't be handled properly"; 163 flash.message = "Unfortunately, your request could not be completed, because the system had to log you in first. Please try again." 164 redirect( url: gscfService.urlAuthRemote(null, session.sessionToken) ) 165 } 166 153 167 return false 154 168 } … … 184 198 // Also never perform synchronization when files are uploaded. That could lead to concurrent modification 185 199 // errors, since the progress of the upload is retrieved many times, while the processing is still busy 186 if( controllerName == " fasta" ) {200 if( controllerName == "import" ) { 187 201 return true; 188 202 } -
trunk/grails-app/conf/BootStrap.groovy
r36 r63 1 1 import nl.tno.massSequencing.auth.*; 2 import nl.tno.massSequencing.AssaySample; 2 3 3 4 class BootStrap { … … 17 18 } 18 19 } 20 21 // Recalculate sequence totals per assaysample, because they might have not 22 // been calculated before 23 AssaySample.recalculateNumSequences() 19 24 } 20 25 def destroy = { -
trunk/grails-app/conf/Config.groovy
r59 r63 62 62 // Path in GSCF that is used after baseURL for adding a new study 63 63 gscf.addStudyPath = "/simpleWizard" 64 gscf.registerSearchPath = "/advancedQuery/refineExternal" 64 65 65 66 grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination -
trunk/grails-app/controllers/masssequencing/SandboxController.groovy
r61 r63 282 282 ) as JSON 283 283 } 284 285 def query = { 286 def q = "SELECT a, a.sample.name, a.assay.name, a.assay.study.name, a.numSequences FROM AssaySample a WHERE ( EXISTS( FROM Auth auth WHERE auth.study = a.assay.study AND auth.canRead = true AND auth.user = :sessionUser ) ) "; 287 println AssaySample.executeQuery( q, [ "sessionUser": User.get( 2 ) ] ) 288 } 284 289 } -
trunk/grails-app/controllers/nl/tno/massSequencing/AssayController.groovy
r60 r63 40 40 "a.study.name", 41 41 "COUNT( DISTINCT s )", 42 "SUM( s d.numSequences ) / COUNT( DISTINCT s )",42 "SUM( s.numSequences ) / COUNT( DISTINCT s )", 43 43 "a.study.studyToken" 44 44 ] … … 48 48 49 49 // Retrieve data from assaySample table 50 def from = "Assay a LEFT JOIN a.assaySamples s LEFT JOIN s.sequenceData sd"50 def from = "Assay a LEFT JOIN a.assaySamples s" 51 51 def where = " EXISTS( FROM Auth auth WHERE auth.study = a.study AND auth.user = :user AND auth.canRead = true )" 52 52 def parameters = [ "user": session.user ] -
trunk/grails-app/controllers/nl/tno/massSequencing/AssaySampleController.groovy
r62 r63 89 89 */ 90 90 protected void renderSequenceLengthHistogram( String title, def assaySamples ) { 91 println "Rendering histogram for " + assaySamples?.size() + " samples"; 92 91 93 def numSequences = assaySamples.collect { it.numSequences() }.sum() 92 94 render( view: "sequenceLengthHistogram", model: [ title: title, numSequences: numSequences, histogram: fastaService.sequenceLengthHistogram( assaySamples ) ] ); … … 200 202 protected List getAssaySamples( params ) { 201 203 def ids = params.list( 'ids' ); 202 204 def tokens = params.list( 'tokens' ); 205 203 206 ids = ids.findAll { it.isLong() }.collect { Long.parseLong( it ) } 204 205 if( !ids ) {207 208 if( !ids && !tokens ) { 206 209 def message = "No assaysample ids given" 207 210 flash.error = message … … 209 212 return; 210 213 } 211 212 return ids.collect { id -> AssaySample.get( id ) }.findAll{ it } 214 215 def samples = []; 216 217 if( ids ) 218 samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.id IN (:ids)", [ "ids": ids ] ); 219 220 if( tokens ) 221 samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.sample.sampleToken IN (:tokens)", [ "tokens": tokens ] ); 222 223 return samples; 213 224 } 214 225 } -
trunk/grails-app/controllers/nl/tno/massSequencing/FastaController.groovy
r58 r63 51 51 sample.save(); 52 52 53 // Recalculate the number of sequences for this sample 54 AssaySample.recalculateNumSequences( sample ); 55 53 56 flash.message = numFiles + " file" + (numFiles != 1 ? "s have" : " has" ) + " been deleted from this sample" 54 57 -
trunk/grails-app/controllers/nl/tno/massSequencing/RunController.groovy
r60 r63 33 33 "r.name", 34 34 "COUNT( DISTINCT a )", 35 "SUM( sd.numSequences )"35 "SUM( a.numSequences )" 36 36 ] 37 37 … … 40 40 41 41 // Retrieve data from assaySample table 42 def from = "Run r LEFT JOIN r.assaySamples a LEFT JOIN a.sequenceData sd"42 def from = "Run r LEFT JOIN r.assaySamples a" 43 43 44 44 // This closure determines what to do with a row that is retrieved from the database. … … 98 98 redirect(controller: 'study', action: 'index') 99 99 return 100 }101 102 // Make sure the newest data is available103 synchronizationService.sessionToken = session.sessionToken104 synchronizationService.user = session.user105 try {106 synchronizationService.synchronizeStudies();107 } catch( Exception e ) {108 log.error "Exception occurred during synchronization in " + params.controller + ": " + e.getMessage()109 redirect( url: synchronizationService.gscfService.urlAuthRemote(params, session.sessionToken) )110 100 } 111 101 … … 199 189 [ 200 190 g.checkBox( name: "ids", value: sampleId, checked: false, onClick: "updateCheckAll(this);" ), 201 g.link( url: "#", onClick:"showSample( " + sampleId + ", ' assay' );", title: "Show sample details" ) { sampleName }, // it.sample.name191 g.link( url: "#", onClick:"showSample( " + sampleId + ", 'run' );", title: "Show sample details" ) { sampleName }, // it.sample.name 202 192 it[ 2 ], // it.assay.study.name 203 193 it[ 3 ], // it.assay.name -
trunk/grails-app/controllers/nl/tno/massSequencing/classification/ClassificationController.groovy
r62 r63 1 1 package nl.tno.massSequencing.classification 2 3 import java.util.List; 2 4 3 5 import nl.tno.massSequencing.* … … 101 103 102 104 protected List getAssaySamples() { 103 // Retrieve assaySamples from ids 104 def assaySampleIds = params.list( 'ids' ); 105 def assaySamples = []; 106 assaySampleIds.each { id -> 107 if( id && id.isLong() ) { 108 def assaySample = AssaySample.get( Long.valueOf( id ) ); 109 if( assaySample ) 110 assaySamples << assaySample; 111 } 105 def ids = params.list( 'ids' ); 106 def tokens = params.list( 'tokens' ); 107 108 ids = ids.findAll { it.isLong() }.collect { Long.parseLong( it ) } 109 110 if( !ids && !tokens ) { 111 def message = "No assaysample ids given" 112 flash.error = message 113 redirect( controller: "run", action: "index" ); 114 return; 112 115 } 113 116 114 return assaySamples; 117 def samples = []; 118 119 if( ids ) 120 samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.id IN (:ids)", [ "ids": ids ] ); 121 122 if( tokens ) 123 samples += AssaySample.executeQuery( "FROM AssaySample a WHERE a.sample.sampleToken IN (:tokens)", [ "tokens": tokens ] ); 124 125 return samples; 115 126 } 116 127 } -
trunk/grails-app/controllers/nl/tno/massSequencing/files/ImportController.groovy
r59 r63 421 421 422 422 def sample = AssaySample.get( filevalue.assaySample ); 423 if( sample ) 423 if( sample ) { 424 424 sample.addToSequenceData( sd ); 425 426 AssaySample.recalculateNumSequences( sample ); 427 } 425 428 426 429 if( !sd.validate() ) { -
trunk/grails-app/controllers/nl/tno/massSequencing/integration/RestController.groovy
r52 r63 33 33 class RestController { 34 34 def synchronizationService 35 def queryService 35 36 36 37 /****************************************************************/ … … 164 165 case "Assay": 165 166 case "Sample": 166 return [ "# sequences", "Forward primer", "Mid name", "Oligo number", "Run name" ]167 return [ "# sequences", "Forward primer", "Mid name", "Oligo number", "Run name", "Classification" ] 167 168 break; 168 169 default: … … 186 187 */ 187 188 def getQueryableFieldData = { 188 println"Get queryable Field data: " + params189 log.debug "Get queryable Field data: " + params 189 190 190 191 def entity = params.entity; … … 218 219 } 219 220 221 def start = System.currentTimeMillis(); 222 def lap 223 220 224 for( token in tokens ) { 225 lap = System.currentTimeMillis(); 226 221 227 def object = getQueryableObject( entity, token ); 222 228 … … 244 250 map[ token ] = [:] 245 251 fields.each { field -> 246 def v = getQueryableFieldValue( entity, object, field );252 def v = queryService.getQueryableFieldValue( entity, object, field ); 247 253 if( v != null ) 248 254 map[ token ][ field ] = v … … 252 258 } 253 259 } 254 260 255 261 render map as JSON 256 262 } 257 263 258 264 /** 259 265 * Searches for a specific entity … … 293 299 def assaySamples 294 300 301 def where = []; 302 def from = "FROM AssaySample a" 303 295 304 switch( entity ) { 296 305 case "Study": 306 where << "a.assay.study = :object"; 307 297 308 assaySamples = object.assays*.assaySamples; 298 309 if( assaySamples ) { … … 301 312 break; 302 313 case "Assay": 314 where << " a.assay = :object "; 303 315 case "Sample": 316 where << " a.sample == :sample "; 304 317 assaySamples = object.assaySamples; 305 318 break; … … 328 341 case "Run name": 329 342 return assaySamples.collect { it.run?.name }.findAll { it != null }.unique(); 343 case "Classification": 344 // Return the names of all species that have been found in the given sample 345 330 346 // Other fields are not handled 331 347 default: … … 335 351 } 336 352 353 354 337 355 private def checkAssayToken( def assayToken ) { 338 356 if( !assayToken || assayToken == null ) { … … 354 372 355 373 /** 356 * Retrieves a list of actions that can be performed on data with a specific entity. 374 * Retrieves a list of actions that can be performed on data with a specific entity. This includes actions that 375 * refine the search result. 357 376 * 358 377 * The module is allowed to return different fields when the user searches for different entities … … 365 384 * a list of searchable fields for all entities is given 366 385 * @return JSON Hashmap with keys being the entities and the values are lists with the action this module can 367 * perform on this entity. The actions as hashmaps themselves, with keys 'name' and 'description' 386 * perform on this entity. The actions as hashmaps themselves, with keys 387 * 'name' Unique name of the action, as used for distinguishing actions 388 * 'description' Human readable description 389 * 'url' URL to send the user to when performing this action. The user is sent there using POST with 390 * the following parameters: 391 * actionName: Name of the action to perform 392 * name: Name of the search that the action resulted from 393 * url: Url of the search that the action resulted from 394 * entity: Type of entity being returned 395 * tokens: List of entity tokens 396 * 'type' (optional) Determines what type of action it is. Possible values: 'default', 'refine', 'export', '' 368 397 */ 369 398 def getPossibleActions = { … … 383 412 case "Study": 384 413 actions[ entity ] = [ 385 [ name: "excel", description: "Export metadata", url: createLink( controller: "study", action: "exportMetaData", absolute: true ) ], 386 [ name: "fasta", description: "Export as fasta", url: createLink( controller: "study", action: "exportAsFasta", absolute: true ) ] 414 [ name: "excel", type: 'export', description: "Export metadata", url: createLink( controller: "study", action: "exportMetaData", absolute: true ) ], 415 [ name: "fasta", type: 'export', description: "Export as fasta", url: createLink( controller: "study", action: "exportAsFasta", absolute: true ) ], 416 [ name: "refine", type: 'refine', description: "Refine by classification", url: createLink( controller: "query", action: "refineExternal", absolute: true ) ], 387 417 ] 388 418 break; 389 419 case "Assay": 390 420 actions[ entity ] = [ 391 [ name: "fasta", description: "Export as fasta", url: createLink( controller: "assay", action: "exportAsFasta", absolute: true ) ], 392 [ name: "excel", description: "Export metadata", url: createLink( controller: "assay", action: "exportMetaData", absolute: true ) ] 421 [ name: "fasta", type: 'export', description: "Export as fasta", url: createLink( controller: "assay", action: "exportAsFasta", absolute: true ) ], 422 [ name: "excel", type: 'export', description: "Export metadata", url: createLink( controller: "assay", action: "exportMetaData", absolute: true ) ], 423 [ name: "refine", type: 'refine', description: "Refine by classification", url: createLink( controller: "query", action: "refineExternal", absolute: true ) ], 393 424 ] 394 425 break; 395 426 case "Sample": 396 427 actions[ entity ] = [ 397 [ name: "fasta", description: "Export as fasta", url: createLink( controller: "sample", action: "exportAsFasta", absolute: true ) ], 398 [ name: "excel", description: "Export metadata", url: createLink( controller: "sample", action: "exportMetaData", absolute: true ) ] 428 [ name: "fasta", type: 'export', description: "Export as fasta", url: createLink( controller: "sample", action: "exportAsFasta", absolute: true ) ], 429 [ name: "excel", type: 'export', description: "Export metadata", url: createLink( controller: "sample", action: "exportMetaData", absolute: true ) ], 430 [ name: "refine", type: 'refine', description: "Refine by classification", url: createLink( controller: "query", action: "refineExternal", absolute: true ) ], 399 431 ] 400 432 break; … … 407 439 render actions as JSON 408 440 } 409 441 410 442 /****************************************************************/ 411 443 /* REST resources for providing basic data to the GSCF */ -
trunk/grails-app/domain/nl/tno/massSequencing/Assay.groovy
r52 r63 70 70 71 71 return numFiles; 72 } 72 } 73 74 public String token() { return assayToken; } 75 73 76 } -
trunk/grails-app/domain/nl/tno/massSequencing/AssaySample.groovy
r59 r63 1 1 package nl.tno.massSequencing 2 3 import org.codehaus.groovy.grails.commons.ApplicationHolder as AH 2 4 3 5 /** … … 11 13 def dataSource 12 14 13 // To be computed at run time 14 private long _numSequences = -1; 15 // To be computed at run time (and saved in cache) 15 16 private float _averageQuality = -1.0; 16 17 private long _numQualScores = -1; … … 19 20 20 21 Integer numUniqueSequences // Number of unique sequences / OTUs. Is only available after preprocessing 21 22 Long numSequences // Number of sequences in this assaySample. Is used in many calculations and therefore stored 23 22 24 String fwOligo 23 25 String fwMidName … … 51 53 52 54 static mapping = { 53 columns { 54 numSequences index:'numsequences_idx' 55 } 55 56 56 sequenceData cascade: "all-delete-orphan" 57 57 sample fetch: 'join' … … 129 129 */ 130 130 public long numSequences() { 131 if( _numSequences > -1 ) 132 return _numSequences; 133 134 if( !sequenceData ) 135 return 0 136 137 long numSequences = 0; 138 sequenceData.each { numSequences += it.numSequences } 139 140 // Save as cache 141 _numSequences = numSequences; 142 143 return numSequences; 131 return numSequences ?: 0; 144 132 } 145 133 … … 196 184 */ 197 185 public void resetStats() { 198 _numSequences = -1;199 186 _numQualScores = -1; 200 187 _averageQuality = -1; … … 230 217 count( s.sequence_file ) AS numSequenceFiles, 231 218 count( s.quality_file ) AS numQualityFiles, 232 sum( s.num_sequences ) AS numSequences,233 219 sum( CASE WHEN s.quality_file IS NOT NULL THEN s.num_sequences ELSE 0 END ) AS numQualScores 234 220 FROM assay_sample a … … 251 237 log.error "ID of the database row and the domain object don't match. DB: " + it.id + ", Domain object: " + assaySamples[ listIndex ]?.id 252 238 } else { 253 assaySamples[ listIndex ]._numSequences = it.numSequences ?: 0;254 239 assaySamples[ listIndex ]._numQualScores = it.numQualScores ?: 0; 255 240 assaySamples[ listIndex ]._numSequenceFiles = it.numSequenceFiles ?: 0; … … 291 276 otherAssaySample.revMidSeq = revMidSeq; 292 277 otherAssaySample.revPrimerSeq = revPrimerSeq; 278 279 otherAssaySample.numSequences = numSequences; 293 280 294 281 // Move attached data … … 352 339 } 353 340 341 numSequences = 0; 342 354 343 resetStats(); 355 344 save(); … … 367 356 Classification.executeUpdate( "DELETE FROM Classification c WHERE c.assaySample = ?", [this]) 368 357 } 358 359 /** 360 * Recalculates the number of sequences for the given assaysample(s) 361 */ 362 public static void recalculateNumSequences( def selection = null ) { 363 def whereClause = ""; 364 def parameters = [:]; 365 366 // Determine which samples to handle 367 if( !selection ) { 368 whereClause = ""; 369 } else if( selection instanceof AssaySample ) { 370 whereClause = "WHERE a = :selection "; 371 parameters[ "selection" ] = selection; 372 } else if( selection instanceof Collection ) { 373 if( selection.findAll { it } ) { 374 whereClause = "WHERE a IN (:selection) "; 375 parameters[ "selection" ] = selection.findAll { it }; 376 } 377 } 378 379 // Flush and clear session before updating 380 def sessionFactory = AH.application.mainContext.sessionFactory; 381 sessionFactory.getCurrentSession().flush(); 382 sessionFactory.getCurrentSession().clear(); 383 384 // Execute update query 385 AssaySample.executeUpdate( "UPDATE AssaySample a SET a.numSequences = ( SELECT SUM( sd.numSequences ) FROM SequenceData sd WHERE sd.sample.id = a.id ) " + whereClause, parameters ); 386 } 387 388 /** 389 * If an assaysample is used for communication to GSCF, the sample token is used. 390 * @return 391 */ 392 public String token() { 393 return sample.token(); 394 } 369 395 } -
trunk/grails-app/domain/nl/tno/massSequencing/Sample.groovy
r57 r63 36 36 ); 37 37 } 38 39 public String token() { return sampleToken; } 38 40 39 41 } -
trunk/grails-app/domain/nl/tno/massSequencing/Study.groovy
r58 r63 96 96 return authorization.isOwner 97 97 } 98 99 public String token() { return studyToken; } 98 100 99 101 } -
trunk/grails-app/domain/nl/tno/massSequencing/classification/Classification.groovy
r62 r63 62 62 63 63 // Determine level names for the necessary levels 64 levels = [:]; 65 minLevel.upto( maxLevel ) { level -> 66 def levelEnum = Taxon.Level.find { it.number() == level } 67 levels[ level ] = levelEnum?.description(); 68 } 64 levels = Taxon.retrieveLevelNames( minLevel, maxLevel ); 69 65 70 66 // First build a list of percentages for each assaysample, in order to have default values … … 127 123 * @return [ maxLevel, minLevel ] 128 124 */ 129 public static determineMinAndMaxLevels( List assaySamples ) { 130 def levels = Classification.executeQuery( "SELECT MAX(t.level), MIN(t.level) FROM Classification c LEFT JOIN c.taxon t LEFT JOIN c.assaySample a WHERE a IN (:assaySamples)", [ "assaySamples": assaySamples ] )[ 0 ]; 125 public static determineMinAndMaxLevels( List assaySamples = null ) { 126 def levels 127 128 if( !assaySamples ) 129 levels = [ null, null ]; 130 else 131 levels = Classification.executeQuery( "SELECT MAX(t.level), MIN(t.level) FROM Classification c LEFT JOIN c.taxon t LEFT JOIN c.assaySample a WHERE a IN (:assaySamples)", [ "assaySamples": assaySamples ] )[ 0 ]; 131 132 132 133 if( levels[ 0 ] == null ) -
trunk/grails-app/domain/nl/tno/massSequencing/classification/Taxon.groovy
r61 r63 314 314 return t 315 315 } 316 317 public static Map retrieveLevelNames( def minLevel = 1, def maxLevel = 6 ) { 318 def levels = [:]; 319 minLevel.upto( maxLevel ) { level -> 320 def levelEnum = Taxon.Level.find { it.number() == level } 321 levels[ level ] = levelEnum?.description(); 322 } 323 324 return levels; 325 } 316 326 317 327 } -
trunk/grails-app/services/nl/tno/massSequencing/ClassificationService.groovy
r62 r63 255 255 def statement = connection.createStatement(); 256 256 257 // This statement ssearches within the sequences for every taxon that is mentioned (as a leaf-node in the tree)257 // This statement searches within the sequences for every taxon that is mentioned (as a leaf-node in the tree) 258 258 // and inserts statistics about those taxons into the classification table. 259 259 // -
trunk/grails-app/services/nl/tno/massSequencing/FastaService.groovy
r60 r63 134 134 def length 135 135 def lengthMatches 136 def currentLength = 0; 137 def countingLines = false; 136 138 try { 137 139 file.eachLine { line -> 138 140 if( line ) { 139 141 if( line[0] == '>' ) { 142 if( countingLines ) { 143 // If counting the length in lines, we must stop now and store the length 144 histogram[ currentLength ] = ( histogram[ currentLength ] ?: 0 ) + 1; 145 countingLines = false; 146 } 147 140 148 // Comments line: find length=### 141 149 lengthMatches = ( line =~ lengthPattern ); 142 150 if( lengthMatches ) { 143 151 length = Integer.valueOf( lengthMatches[0][1] ); 152 153 histogram[ length ] = ( histogram[length] ?: 0 ) + 1; 144 154 } else { 145 length = 'unknown' 155 // Length is not mentioned in the comments line 156 countingLines = true; 157 currentLength = 0; 146 158 } 147 148 histogram[ length ] = ( histogram[length] ?: 0 ) + 1; 159 } else if( countingLines ) { 160 // Compute the length by counting the files themselves. 161 currentLength += line.trim().size(); 149 162 } 150 163 } … … 155 168 156 169 log.trace "Finished parsing FASTA " + file.getName() + ": " + ( System.nanoTime() - startTime ) / 1000000L 157 170 log.trace "Histogram: " + histogram 171 158 172 return histogram; 159 173 } … … 569 583 570 584 assaySample.sequenceData.each { sequenceData -> 571 copyFastaFileForExport( fileService.get( sequenceData.sequenceFile, permanentDirectory ), currentTag.tag, zipWriter) 585 if( sequenceData && sequenceData.sequenceFile ) 586 copyFastaFileForExport( fileService.get( sequenceData.sequenceFile, permanentDirectory ), currentTag.tag, zipWriter) 572 587 } 573 588 } … … 584 599 585 600 assaySample.sequenceData.each { sequenceData -> 586 copyQualFileForExport( fileService.get( sequenceData.qualityFile, permanentDirectory ), currentTag.tag, zipWriter) 601 if( sequenceData && sequenceData.sequenceFile && sequenceData.qualityFile ) 602 copyQualFileForExport( fileService.get( sequenceData.qualityFile, permanentDirectory ), currentTag.tag, zipWriter) 587 603 } 588 604 } … … 595 611 } catch( Exception e ) { 596 612 log.error "Error while writing to fastafile or qualfile: " + e.getMessage(); 613 e.printStackTrace(); 597 614 } finally { 598 615 // Always close zip entry … … 779 796 780 797 String line = null 781 String newLine = null798 String newLine = "" 782 799 String sequence = ""; 783 800 … … 806 823 length = Integer.valueOf( lengthMatches[0][1] ) + tagLength; 807 824 newLine = lengthMatches.replaceAll( "length=" + length ); 825 } else { 826 newLine = line; 808 827 } 809 828 … … 823 842 } catch( Exception e ) { 824 843 log.error( "An error occurred while copying contents from " + inFile.getName() + ": " + e.getMessage() ); 844 e.printStackTrace(); 825 845 return false; 826 846 } … … 897 917 length = Integer.valueOf( lengthMatches[0][1] ) + tagLength; 898 918 newLine = lengthMatches.replaceAll( "length=" + length ); 919 } else { 920 newLine = line 899 921 } 900 922 -
trunk/grails-app/services/nl/tno/massSequencing/integration/GscfService.groovy
r53 r63 24 24 * @return URL to redirect the user to 25 25 */ 26 public String urlAuthRemote( def params, def token ) {26 public String urlAuthRemote( def params, def token, appendParameters = true ) { 27 27 def redirectURL = "${config.gscf.baseURL}/login/auth_remote?moduleURL=${this.moduleURL()}&consumer=${this.consumerID()}&token=${token}&" 28 29 def returnUrl = config.grails.serverURL 30 if (params.controller != null){ 31 returnUrl += "/${params.controller}" 32 if (params.action != null){ 33 returnUrl += "/${params.action}" 34 if (params.id != null){ 35 returnUrl += "/${params.id}" 28 def returnUrl 29 30 // Append other parameters (but only if this request is a GET request) 31 if( appendParameters && params ) { 32 def request = RequestContextHolder.getRequestAttributes().getRequest(); 33 34 if( request.method != "GET" ) { 35 // Only GET parameters can be sent to the user. The calling method can call the method again with the appendParameters 36 // property set to false or without a parameters object. 37 throw new Exception( "Parameters can only be added in GET requests" ); 38 } 39 40 returnUrl = config.grails.serverURL 41 if (params.controller != null){ 42 returnUrl += "/${params.controller}" 43 if (params.action != null){ 44 returnUrl += "/${params.action}" 45 if (params.id != null){ 46 returnUrl += "/${params.id}" 47 } 36 48 } 37 49 } 38 } 39 40 // Append other parameters 41 returnUrl += "?" + params.collect { 42 if( it.key != "controller" && it.key != "action" && it.key != "id" ) 43 return it.key.toString().encodeAsURL() + "=" + it.value.toString().encodeAsURL(); 44 else 45 return "" 46 }.findAll { it }.join( "&" ); 50 51 returnUrl += "?" + params.collect { param -> 52 if( param.key != "controller" && param.key != "action" && param.key != "id" ) { 53 if( param.value instanceof List ) { 54 return param.value.collect { return param.key.toString().encodeAsURL() + "=" + it.toString().encodeAsURL() }.findAll { it }.join( "&" ) 55 } else if( param.value instanceof Map ) { 56 // Discard this parameter as it is present in other keys as well. 57 } else { 58 return param.key.toString().encodeAsURL() + "=" + param.value.toString().encodeAsURL(); 59 } 60 } else { 61 return "" 62 } 63 }.findAll { it }.join( "&" ); 64 } else { 65 returnUrl = config.grails.serverURL; 66 } 47 67 48 68 // After logging in, send the user to /synchronize/authorization first to synchronize … … 72 92 } 73 93 94 /** 95 * Returns the URL to register an external search with GSCF 96 * 97 * @return URL to redirect the user to 98 */ 99 public String urlRegisterSearch( def search ) { 100 return config.gscf.baseURL + config.gscf.registerSearchPath 101 } 102 74 103 /** 75 104 * Retrieves the currently logged in user from GSCF … … 400 429 } 401 430 402 log.info("GSCF REST-RESP: ${jsonResponse}") 431 if( jsonResponse.size() > 2000 ) 432 log.info("GSCF REST-RESP: " + jsonResponse[0..2000] + "..." ) 433 else 434 log.info("GSCF REST-RESP: " + jsonResponse ) 403 435 } catch(Exception e) { 404 436 log.error("Parsing GSCF JSON response failed at ${addr}. Reponse was " + connection.content.text,e) -
trunk/grails-app/services/nl/tno/massSequencing/integration/SynchronizationService.groovy
r52 r63 671 671 // Create a new assay-sample combination 672 672 log.trace( "Connecting sample to assay" ) 673 assaySampleFound = new AssaySample( );673 assaySampleFound = new AssaySample( numSequences: 0 ); 674 674 675 675 assay.addToAssaySamples( assaySampleFound ); 676 676 sampleFound.addToAssaySamples( assaySampleFound ); 677 677 678 assaySampleFound.save() 678 if( !assaySampleFound.save() ) { 679 log.error( "Error while connecting sample to assay: " + assaySampleFound.errors ) 680 } 679 681 } 680 682 } -
trunk/grails-app/views/classification/show.gsp
r62 r63 36 36 </p> 37 37 </g:if> 38 <table border="0" class="sortable classification ">38 <table border="0" class="sortable classification scrollX"> 39 39 <thead> 40 40 <tr> -
trunk/grails-app/views/common/_topnav.gsp
r53 r63 9 9 </ul> 10 10 </li> 11 <li><g:link controller="query">Query</g:link></li> 11 12 <li> 12 13 <a href="#" onClick="return false;">GSCF</a> -
trunk/grails-app/views/import/showProcessScreen.gsp
r60 r63 33 33 data: "${processParameters*.toString().join("&")}", 34 34 success: function(data) { 35 36 35 // Stop update progress bar 37 36 clearTimeout( progressInterval ); 37 38 alert( "success" ); 38 39 39 40 window.location.replace( "${finishUrl.encodeAsJavaScript()}" ); 40 41 }, 41 42 error: function(xhr, textStatus, errorThrown) { 42 43 43 44 // Stop update progress bar (but update it for the last time) 44 45 updateProgress() -
trunk/web-app/css/buttons.css
r62 r63 57 57 } 58 58 59 /* Classification */ 59 60 .options a.classification { 60 61 background-image: url(../plugins/famfamfam-1.0.1/images/icons/tag_blue.png); … … 69 70 } 70 71 72 /* Querying */ 73 .options a.searchIn { 74 background-image: url(../plugins/famfamfam-1.0.1/images/icons/arrow_branch.png); 75 } 76 .options a.search { 77 background-image: url(../plugins/famfamfam-1.0.1/images/icons/arrow_undo.png); 78 } 79 .options a.discard { 80 background-image: url(../plugins/famfamfam-1.0.1/images/icons/basket_remove.png); 81 } 82 .options a.listPrevious { 83 background-image: url(../plugins/famfamfam-1.0.1/images/icons/basket.png); 84 } 85 .options a.combine { 86 background-image: url(../plugins/famfamfam-1.0.1/images/icons/arrow_join.png); 87 } -
trunk/web-app/js/paginate.js
r62 r63 95 95 iCookieDuration: 86400, // Save cookie one day 96 96 sScrollY: '350px', 97 sScrollX: '100%',97 sScrollX: $el.hasClass( 'scrollX' ) ? '100%' : '', 98 98 bScrollCollapse: true, 99 99 aoColumnDefs: [ … … 175 175 176 176 function checkAllPaginatedClientSide( paginatedTable ) { 177 var paginatedTable = $(input).closest( '.paginate' );178 177 var checkAll = $( '#checkAll', paginatedTable ); 179 178
Note: See TracChangeset
for help on using the changeset viewer.