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

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

Solved bug in moving data to trash

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