source: trunk/grails-app/services/nl/tno/metagenomics/integration/TrashService.groovy @ 22

Last change on this file since 22 was 22, checked in by robert@…, 8 years ago

Implemented authorization checks on file downloads

File size: 12.2 KB
Line 
1package nl.tno.metagenomics.integration
2
3import nl.tno.metagenomics.*
4import nl.tno.metagenomics.auth.Auth;
5
6
7class TrashService {
8
9        static transactional = true
10
11        /**
12         * Moves the valuable data from a study to trash and deletes the study
13         * @param               Study to move to trash
14         */
15        def moveToTrash( Study study ) {
16                log.trace "Moving study " + study + " to trash";
17                if( study.trashcan )
18                        return
19
20                saveDataInTrash( study );
21               
22                def l = []
23                if( study.auth ) {
24                        l += study.auth
25                       
26                        l.each { auth ->
27                                auth.user?.removeFromAuth( auth );
28                                study.removeFromAuth( auth );
29                        }
30                }
31                               
32                study.delete(flush:true);
33        }
34
35        /**
36         * Moves the valuable data from an assay to trash and deletes the assay
37         * @param               Assay to move to trash
38         */
39        def moveToTrash( Assay assay ) {
40                saveDataInTrash( assay );
41
42                // Remove associations
43                def l = []
44                if( assay.runs ) {
45                        l += assay.runs
46                       
47                        l.each {
48                                if( it ) {
49                                        assay.removeFromRuns( it );
50                                        it.removeFromAssays( assay );
51                                }
52                        }
53                }
54               
55                l = []
56                if( assay.assaySamples ) {
57                        l += assay.assaySamples
58                       
59                        l.each {
60                                it.sample.removeFromAssaySamples( it );
61                                assay.removeFromAssaySamples( it );
62                        }
63                }
64
65                def study = assay.study
66                if( study ) {
67                        study.removeFromAssays( assay );
68                }
69        }
70
71        /**
72         * Moves the valuable data from a sample to trash and deletes the sample
73         * @param               Sample to move to trash
74         */
75        def moveToTrash( Sample sample ) {
76                saveDataInTrash( sample );
77
78                // Remove associations
79                def l = []
80                if( sample.assaySamples ) {
81                        l += sample.assaySamples
82                       
83                        l.each {
84                                it.assay.removeFromAssaySamples( it );
85                                sample.removeFromAssaySamples( it );
86                        }
87                }
88               
89                def study = sample.study
90                sample.study.removeFromSamples( sample );
91                study.save();
92        }
93
94        /**
95        * Moves the valuable data from an assaySample to trash and deletes the assay
96        * @param                Assay to move to trash
97        */
98   def moveToTrash( AssaySample assaySample ) {
99           saveDataInTrash( assaySample );
100
101           // Remove associations
102           if( assaySample.run ) {
103                   assaySample.run.removeFromAssaySamples( assaySample );
104           }
105           
106           if( assaySample.assay ) {
107                   assaySample.assay.removeFromAssaySamples( assaySample );
108           }
109
110           if( assaySample.sample ) {
111                   assaySample.sample.removeFromAssaySamples( assaySample );
112           }
113           
114           def l = []
115           if( assaySample.sequenceData ) {
116                   l += assaySample.sequenceData
117                   
118                   l.each {
119                           if( it ) {
120                                        assaySample.removeFromSequenceData( it );
121                           }
122                   }
123           }
124           
125   }
126       
127        /**
128         * Saves data from the study in the trash can (if any data exists)
129         * @param study         Study to save data from
130         * @return
131         */
132        def saveDataInTrash( Study study ) {
133                Study trashcan = this.giveTrashcan()
134
135                if( !trashcan ) {
136                        log.warn "No trashcan (study with trashcan property set to true) found in the database when deleting study " + study.name + ". Possibly valuable data is deleted forever."
137                        return;
138                }
139
140                // Loop through all assays, and see if there are assay samples
141                // that have data
142                study.assays.each { assay ->
143                        saveDataInTrash( assay );
144                }
145        }
146
147        /**
148         * Saves data from the assay in the trash can (if any data exists)
149         * @param study         Assay to save data from
150         * @return
151         */
152        def saveDataInTrash( Assay assay ) {
153                Study trashcan = this.giveTrashcan()
154
155                if( !trashcan ) {
156                        log.warn "No trashcan (study with trashcan property set to true) found in the database when deleting assay " + assay.name + ". Possibly valuable data is deleted forever."
157                        return;
158                }
159
160                def assaySamples = assay.assaySamples.findAll { it.containsData() }
161
162                // For every assay sample that contains data, save that data in the trashcan
163                if( assaySamples.size() > 0 ) {
164                        // Create a dummy assay copy of the existing assay
165                        String newAssayToken = 'TrashAssay ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
166
167                        Assay dummyAssay = new Assay( assayToken: newAssayToken, name: assay.name, study: trashcan );
168                        trashcan.addToAssays( dummyAssay );
169                        dummyAssay.save()
170
171                        assaySamples.each { assaySample ->
172                                Sample sample = assaySample.sample
173
174                                // Create dummy sample
175                                String newSampleToken = 'TrashSample ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
176                                Sample dummySample = Sample.cloneSample( sample, newSampleToken, trashcan );
177                                trashcan.addToSamples( dummySample );
178                                dummySample.save()
179
180                                // Create dummy assay sample
181                                AssaySample dummyAssaySample = new AssaySample( assay: dummyAssay, sample: dummySample );
182
183                                dummyAssay.addToAssaySamples( dummyAssaySample );
184                                dummySample.addToAssaySamples( dummyAssaySample );
185                                dummyAssaySample.save();
186
187                                // Move data from this assay sample to the trash version of it
188                                assaySample.moveValuableDataTo( dummyAssaySample );
189                               
190                                // Remove the assaySample from its run, since otherwise the statistics of the run (#sequences for example)
191                                // are not correct anymore and the assaySample will be resaved after delete
192                                dummyAssaySample.run?.removeFromAssaySamples( dummyAssaySample );
193                               
194                                dummyAssaySample.save();
195                        }
196                }
197               
198                // Remove all assaysamples from this assay from their run
199                assay.assaySamples?.each { assaySample ->
200                        assaySample.run?.removeFromAssaySamples( assaySample );
201                }
202               
203                // Remove this assay from the runs, since otherwise the samples will be resaved upon delete
204                if( assay.runs ) {
205                        def l = [] + assay.runs
206                        l.each {
207                                it.removeFromAssays( assay );
208                        }
209                }
210        }
211
212        /**
213         * Saves data from the sample in the trash can (if any data exists)
214         * @param study         Sample to save data from
215         * @return
216         */
217        def saveDataInTrash( Sample sample ) {
218                Study trashcan = this.giveTrashcan()
219
220                if( !trashcan ) {
221                        log.warn "No trashcan (study with trashcan property set to true) found in the database when deleting sample " + sample.name + ". Possibly valuable data is deleted forever."
222                        return;
223                }
224
225                def assaySamples = sample.assaySamples.findAll { it.containsData() }
226
227                // For every assay sample that contains data, save that data in the trashcan
228                if( assaySamples.size() > 0 ) {
229                        // Create dummy sample
230                        String newSampleToken = 'TrashSample ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
231                        Sample dummySample = Sample.cloneSample( sample, newSampleToken, trashcan );
232                        trashcan.addToSamples( dummySample );
233                        dummySample.save()
234
235                        assaySamples.each { assaySample ->
236                                Assay assay = assaySample.assay;
237
238                                // Create a dummy assay copy of the existing assay
239                                String newAssayToken = 'TrashAssay ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
240
241                                Assay dummyAssay = new Assay( assayToken: newAssayToken, name: assay.name, study: trashcan );
242                                trashcan.addToAssays( dummyAssay );
243                                dummyAssay.save()
244
245                                // Create dummy assay sample
246                                AssaySample dummyAssaySample = new AssaySample( assay: dummyAssay, sample: dummySample );
247
248                                dummyAssay.addToAssaySamples( dummyAssaySample );
249                                dummySample.addToAssaySamples( dummyAssaySample );
250                                dummyAssaySample.save();
251
252                                // Move data from this assay sample to the trash version of it
253                                assaySample.moveValuableDataTo( dummyAssaySample );
254                               
255                                // Remove the assaySample from its run, since otherwise the statistics of the run (#sequences for example)
256                                // are not correct anymore
257                                dummyAssaySample.run?.removeFromAssaySamples( dummyAssaySample );
258
259                                dummyAssaySample.save();
260                        }
261                }
262               
263                // Remove all assaysamples from this assay from their run
264                sample.assaySamples?.each { assaySample ->
265                        assaySample.run?.removeFromAssaySamples( assaySample );
266                }
267        }
268
269       
270        /**
271        * Saves data from the assay-sample in the trash can (if any data exists)
272        * @param study          Sample to save data from
273        * @return
274        */
275   def saveDataInTrash( AssaySample assaySample ) {
276           Study trashcan = this.giveTrashcan()
277
278           if( !trashcan ) {
279                   log.warn "No trashcan (study with trashcan property set to true) found in the database when deleting sample " + sample.name + ". Possibly valuable data is deleted forever."
280                   return;
281           }
282
283           // For every assay sample that contains data, save that data in the trashcan
284           if( assaySample.containsData() ) {
285                   // Create dummy sample
286                   String newSampleToken = 'TrashSample ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
287                   Sample dummySample = Sample.cloneSample( assaySample.sample, newSampleToken, trashcan );
288                   trashcan.addToSamples( dummySample );
289                   dummySample.save()
290
291                   Assay assay = assaySample.assay;
292
293                   // Create a dummy assay copy of the existing assay
294                   String newAssayToken = 'TrashAssay ' + new Date().format( 'yyyyMMddHHmmssSSS') + ( Math.random() * 10000 );
295
296                   Assay dummyAssay = new Assay( assayToken: newAssayToken, name: assay.name, study: trashcan );
297                   trashcan.addToAssays( dummyAssay );
298                   dummyAssay.save()
299
300                   // Create dummy assay sample
301                   AssaySample dummyAssaySample = new AssaySample( assay: dummyAssay, sample: dummySample );
302
303                   dummyAssay.addToAssaySamples( dummyAssaySample );
304                   dummySample.addToAssaySamples( dummyAssaySample );
305                   dummyAssaySample.save();
306
307                   // Move data from this assay sample to the trash version of it
308                   assaySample.moveValuableDataTo( dummyAssaySample );
309                   dummyAssaySample.save();
310           }
311   }
312
313        /**
314         * Retrieves the trashcan study from the database
315         */
316        def giveTrashcan = {
317                def study = Study.findByTrashcan( true );
318
319                if( !study )
320                        return null;
321                else
322                        return study
323        }
324       
325        /**
326         * Creates a new trashcan study. Should only be used by the bootstrap to create a trashcan
327         */
328        def createTrashcan = {
329                def study = new Study( name: "Trashcan", studyToken: "trash", trashcan: true )
330                study.save();
331        }
332       
333        /**
334         * Sets up authorization for the trashcan study
335         */
336        def setupAuthorization = { study, admin ->
337                if( study && admin ) {
338                        def a = Auth.createAuth(study, admin);
339                        a.canRead = true;
340                        a.canWrite = true;
341                        a.isOwner = true;
342                        a.save();
343                }
344        }
345
346        /**
347         * Cleans up the trash by removing empty assays or samples. Empty means:
348         *      - an assay with samples
349         *  - a sample without sequences, tag sequence and oligo number
350         * 
351         *  Also removes samples in trash that are not referenced by an assaysample
352         */
353        def cleanTrash = {
354                def studies = Study.findAllByTrashcan( true );
355
356                studies.each { study ->
357                        def numAssays = study.assays?.size()
358                        def assayList = study.assays?.toList();
359
360                        def numSamples
361                        def sampleList
362
363                        // Loop backwards through the assays in order to facilitate removing assays
364                        for( def i = numAssays -1; i >= 0; i-- ) {
365                                // Loop through all samples and remove the ones that are empty
366                                if( assayList[ i ].assaySamples != null ) {
367                                        numSamples = assayList[ i ].assaySamples.size()
368                                        sampleList = assayList[ i ].assaySamples.toList();
369
370                                        for( def j = numSamples - 1; j >= 0; j-- ) {
371                                                def s = sampleList[ j ];
372                                                if( !s.containsData() ) {
373                                                        assayList[ i ].removeFromAssaySamples( s );
374                                                        s.sample?.delete();
375                                                        s.delete();
376                                                }
377                                        }
378                                }
379
380                                // Now check if there are samples left. Otherwise, remove the assay
381                                if( assayList[i].assaySamples == null || assayList[i].assaySamples.size() == 0 ) {
382                                        study.removeFromAssays( assayList[ i ] );
383                                        assayList[i].delete();
384                                }
385                        }
386
387                        // Loop through samples and delete the ones not referenced by an assaysample
388                        /*
389                         numSamples = study.samples?.size()
390                         sampleList = study.samples?.toList();
391                         for( def j = numSamples - 1; j >= 0; j-- ) {
392                         def s = sampleList[ j ];
393                         if( s.assaySamples == null || s.assaySamples.size() == 0 ) {
394                         study.removeFromSamples(s);
395                         s.delete(flush:true);
396                         }
397                         }
398                         */
399                }
400        }
401
402        /**
403         * Restore an assay from trash and put the contents of the assay in another assay
404         * @param assay
405         * @param restoreTo
406         */
407        public void restoreAssay( Assay assay, Assay restoreTo ) {
408                // Loop through all assaysamples and restore the ones that have a matching name
409                assay.assaySamples.each { assaySample ->
410                        if( assaySample ) {
411                                // Find a sample with the same name
412                                def restoreSample = restoreTo.assaySamples.find { it.sample?.name == assaySample.sample?.name }
413
414                                if( restoreSample ) {
415                                        this.restoreSample( assaySample, restoreSample );
416                                }
417                        }
418                }
419        }
420
421        /**
422         * Restore a sample from trash and put the contents of the sample into another sample
423         * @param sample
424         * @param restoreTo
425         */
426        public void restoreSample( AssaySample sample, AssaySample restoreTo ) {
427                sample.moveValuableDataTo( restoreTo );
428                restoreTo.save();
429        }
430}
Note: See TracBrowser for help on using the repository browser.