Changeset 1233


Ignore:
Timestamp:
Dec 2, 2010, 6:03:36 PM (6 years ago)
Author:
work@…
Message:
  • introduced deleteSample method to be sure a sample -and it's relations- are correctly deleted.
  • hopefully this resolves #223
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/domain/dbnp/studycapturing/Study.groovy

    r1222 r1233  
    1212 */
    1313class Study extends TemplateEntity {
    14         static searchable = true
     14        static searchable = true
    1515
    1616        SecUser owner           // The owner of the study. A new study is automatically owned by its creator.
    17         String title        // The title of the study
    18         String code             // currently used as the external study ID, e.g. to reference a study in a SAM module
     17        String title            // The title of the study
     18        String code              // currently used as the external study ID, e.g. to reference a study in a SAM module
    1919        Date dateCreated
    2020        Date lastUpdated
     
    2727        List assays
    2828        boolean published = false // Determines whether a study is private (only accessable by the owner and writers) or published (also visible to readers)
    29     boolean publicstudy = false  // Determines whether anonymous users are allowed to see this study. This has only effect when published = true
    30        
    31         static hasMany = [             
     29        boolean publicstudy = false  // Determines whether anonymous users are allowed to see this study. This has only effect when published = true
     30
     31        static hasMany = [
    3232                subjects: Subject,
    3333                samplingEvents: SamplingEvent,
     
    3838                persons: StudyPerson,
    3939                publications: Publication,
    40                 readers: SecUser,
    41                 writers: SecUser
     40                readers: SecUser,
     41                writers: SecUser
    4242        ]
    4343
    4444        static constraints = {
    4545                owner(nullable: true, blank: true)
    46                 code(nullable:false, blank:true,unique:true)
     46                code(nullable: false, blank: true, unique: true)
    4747
    4848                // TODO: add custom validator for 'published' to assess whether the study meets all quality criteria for publication
     
    6060        // The external identifier (studyToken) is currently the code of the study.
    6161        // It is used from within dbNP submodules to refer to particular study in this GSCF instance.
     62
    6263        def getToken() { code }
    6364
     
    7677                        name: 'code',
    7778                        type: TemplateFieldType.STRING,
    78                         preferredIdentifier:true,
     79                        preferredIdentifier: true,
    7980                        comment: 'Fill out the code by which many people will recognize your study',
    8081                        required: true),
     
    102103         */
    103104        def List<Event> getOrphanEvents() {
    104                 def orphans =   events.findAll { event -> !event.belongsToGroup(eventGroups) } +
    105                                                 samplingEvents.findAll { event -> !event.belongsToGroup(eventGroups) }
     105                def orphans = events.findAll { event -> !event.belongsToGroup(eventGroups) } +
     106                        samplingEvents.findAll { event -> !event.belongsToGroup(eventGroups) }
    106107
    107108                return orphans
     
    129130         */
    130131        List<Template> giveAllAssayTemplates() {
    131                 TemplateEntity.giveTemplates(( (assays) ? assays : [] ))
     132                TemplateEntity.giveTemplates(((assays) ? assays : []))
    132133        }
    133134
     
    147148                // gives trouble when asking .size() to the result
    148149                // So we also use giveTemplates here
    149                 TemplateEntity.giveTemplates( ((events) ? events : []) + ((samplingEvents) ? samplingEvents : []) )
    150         }
    151 
     150                TemplateEntity.giveTemplates(((events) ? events : []) + ((samplingEvents) ? samplingEvents : []))
     151        }
    152152
    153153        /**
     
    200200        }
    201201
    202 
    203202        /**
    204203         * Delete a specific subject from this study, including all its relations
    205204         * @param subject The subject to be deleted
    206          * @return A String which contains a (user-readable) message describing the changes to the database
    207          */
    208         String deleteSubject(Subject subject) {
    209                 String msg = "Subject ${subject.name} was deleted"
    210 
     205         * @void
     206         */
     207        void deleteSubject(Subject subject) {
    211208                // Delete the subject from the event groups it was referenced in
    212209                this.eventGroups.each {
    213210                        if (it.subjects.contains(subject)) {
    214211                                it.removeFromSubjects(subject)
    215                                 msg += ", deleted from event group '${it.name}'"
    216212                        }
    217213                }
     
    219215                // Delete the samples that have this subject as parent
    220216                this.samples.findAll { it.parentSubject.equals(subject) }.each {
    221                         // This should remove the sample itself too, because of the cascading belongsTo relation
    222                         this.removeFromSamples(it)
    223                         // But apparently it needs an explicit delete() too
    224                         it.delete()
    225                         msg += ", sample '${it.name}' was deleted"
     217                        this.deleteSample(it)
    226218                }
    227219
    228220                // This should remove the subject itself too, because of the cascading belongsTo relation
    229221                this.removeFromSubjects(subject)
     222
    230223                // But apparently it needs an explicit delete() too
    231224                subject.delete()
    232 
    233                 return msg
    234225        }
    235226
     
    257248         * Delete an event from the study, including all its relations
    258249         * @param Event
    259          * @return String
    260          */
    261         String deleteEvent(Event event) {
    262                 String msg = "Event ${event} was deleted"
    263 
     250         * @void
     251         */
     252        void deleteEvent(Event event) {
    264253                // remove event from the study
    265254                this.removeFromEvents(event)
     
    269258                        eventGroup.removeFromEvents(event)
    270259                }
    271 
    272                 return msg
     260        }
     261
     262        /**
     263         * Delete a sample from the study, including all its relations
     264         * @param Event
     265         * @void
     266         */
     267        void deleteSample(Sample sample) {
     268                // remove the sample from the study
     269                this.removeFromSamples(sample)
     270
     271                // remove the sample from any sampling events it belongs to
     272                this.samplingEvents.findAll { it.samples.any { it == sample }}.each {
     273                        it.removeFromSamples(sample)
     274                }
     275
     276                // remove the sample from any assays it belongs to
     277                this.assays.findAll { it.samples.any { it == sample }}.each {
     278                        it.removeFromSamples(sample)
     279                }
     280
     281                // Also here, contrary to documentation, an extra delete() is needed
     282                // otherwise date is not properly deleted!
     283                sample.delete()
    273284        }
    274285
     
    276287         * Delete a samplingEvent from the study, including all its relations
    277288         * @param SamplingEvent
    278          * @return String
    279          */
    280         String deleteSamplingEvent(SamplingEvent samplingEvent) {
    281                 String msg = "SamplingEvent ${samplingEvent} was deleted"
    282 
     289         * @void
     290         */
     291        void deleteSamplingEvent(SamplingEvent samplingEvent) {
    283292                // remove event from eventGroups
    284293                this.eventGroups.each() { eventGroup ->
     
    289298                this.samples.findAll { it.parentEvent.equals(samplingEvent) }.each {
    290299                        // This should remove the sample itself too, because of the cascading belongsTo relation
    291                         this.removeFromSamples(it)
    292                         // But apparently it needs an explicit delete() too
    293                         it.delete()
    294                         msg += ", sample '${it.name}' was deleted"
     300                        this.deleteSample(it)
    295301                }
    296302
     
    302308                // (Which can be verified by outcommenting this line, then SampleTests.testDeleteViaParentSamplingEvent fails
    303309                samplingEvent.delete()
    304 
    305                 return msg
    306         }
    307        
     310        }
     311
    308312        /**
    309313         * Delete an eventGroup from the study, including all its relations
    310314         * @param EventGroup
    311          * @return String
    312          */
    313         String deleteEventGroup(EventGroup eventGroup) {
    314                 String msg = "EventGroup ${eventGroup} was deleted"
    315 
     315         * @void
     316         */
     317        void deleteEventGroup(EventGroup eventGroup) {
    316318                // If the event group contains sampling events
    317319                if (eventGroup.samplingEvents) {
     
    328330                                this.samples.findAll { sample ->
    329331                                        (
    330                                                 (eventGroup.subjects.findAll {
    331                                                         it.equals(sample.parentSubject)
    332                                                 })
     332                                        (eventGroup.subjects.findAll {
     333                                                it.equals(sample.parentSubject)
     334                                        })
    333335                                                &&
    334336                                                (eventGroup.samplingEvents.findAll {
    335337                                                        (
    336                                                                 (it.id && sample.parentEvent.id && it.id==sample.parentEvent.id)
     338                                                        (it.id && sample.parentEvent.id && it.id == sample.parentEvent.id)
    337339                                                                ||
    338340                                                                (it.getIdentifier() == sample.parentEvent.getIdentifier())
     
    344346                                }.each() { sample ->
    345347                                        // remove sample from study
    346 
    347                                         // -------
    348                                         // NOTE, the right samples are found, but the don't
    349                                         // get deleted from the database!
    350                                         // -------
    351 
    352                                         println ".removing sample '${sample.name}' from study '${this.title}'"
    353                                         msg += ", sample '${sample.name}' was deleted"
    354                                         this.removeFromSamples( sample )
    355 
    356                                         // remove the sample from any sampling events it belongs to
    357                                         this.samplingEvents.findAll { it.samples.any { it == sample }} .each {
    358                                                 println ".removed sample ${sample.name} from sampling event ${it} at ${it.getStartTimeString()}"
    359                                                 it.removeFromSamples(sample)
    360                                         }
    361 
    362                                         // remove the sample from any assays it belongs to
    363                                         this.assays.findAll { it.samples.any { it == sample }} .each {
    364                                                 println ".removed sample ${sample.name} from assay ${it.name}"
    365                                                 it.removeFromSamples(sample)
    366                                         }
    367 
    368                                         // Also here, contrary to documentation, an extra delete() is needed
    369                                         // otherwise date is not properly deleted!
    370                                         sample.delete()
     348                                        this.deleteSample(sample)
    371349                                }
    372350                        }
    373351
    374352                        // remove all samplingEvents from this eventGroup
    375                         eventGroup.samplingEvents.findAll{}.each() {
     353                        eventGroup.samplingEvents.findAll {}.each() {
    376354                                eventGroup.removeFromSamplingEvents(it)
    377                                 println ".removed samplingEvent '${it.name}' from eventGroup '${eventGroup.name}'"
    378                                 msg += ", samplingEvent '${it.name}' was removed from eventGroup '${eventGroup.name}'"
    379355                        }
    380356                }
     
    383359                if (eventGroup.subjects) {
    384360                        // remove all subject from this eventGroup
    385                         eventGroup.subjects.findAll{}.each() {
     361                        eventGroup.subjects.findAll {}.each() {
    386362                                eventGroup.removeFromSubjects(it)
    387                                 println ".removed subject '${it.name}' from eventGroup '${eventGroup.name}'"
    388                                 msg += ", subject '${it.name}' was removed from eventGroup '${eventGroup.name}'"
    389363                        }
    390364                }
    391365
    392366                // remove the eventGroup from the study
    393                 println ".remove eventGroup '${eventGroup.name}' from study '${this.title}'"
    394367                this.removeFromEventGroups(eventGroup)
    395368
     
    397370                // otherwise cascaded deletes are not properly performed
    398371                eventGroup.delete()
    399 
    400                 return msg
    401         }
    402 
    403     /**
    404      * Returns true if the given user is allowed to read this study
    405      */
    406     public boolean canRead(SecUser loggedInUser) {
    407         // Anonymous readers are only given access when published and public
    408         if( loggedInUser == null ) {
    409             return this.publicstudy && this.published;
    410         }
     372        }
     373
     374        /**
     375         * Returns true if the given user is allowed to read this study
     376         */
     377        public boolean canRead(SecUser loggedInUser) {
     378                // Anonymous readers are only given access when published and public
     379                if (loggedInUser == null) {
     380                        return this.publicstudy && this.published;
     381                }
    411382
    412383                // Administrators are allowed to read every study
    413                 if( loggedInUser.hasAdminRights() ) {
     384                if (loggedInUser.hasAdminRights()) {
    414385                        return true;
    415386                }
    416387
    417         // Owners and writers are allowed to read this study
    418         if( this.owner == loggedInUser || this.writers.contains(loggedInUser) ) {
    419             return true
    420         }
    421            
    422         // Readers are allowed to read this study when it is published
    423         if( this.readers.contains(loggedInUser) && this.published ) {
    424             return true
    425         }
    426        
    427         return false
    428     }
    429 
    430     /**
    431     * Returns true if the given user is allowed to write this study
    432     */
    433     public boolean canWrite(SecUser loggedInUser) {
    434         if( loggedInUser == null ) {
    435             return false;
    436         }
     388                // Owners and writers are allowed to read this study
     389                if (this.owner == loggedInUser || this.writers.contains(loggedInUser)) {
     390                        return true
     391                }
     392
     393                // Readers are allowed to read this study when it is published
     394                if (this.readers.contains(loggedInUser) && this.published) {
     395                        return true
     396                }
     397
     398                return false
     399        }
     400
     401        /**
     402        * Returns true if the given user is allowed to write this study
     403        */
     404        public boolean canWrite(SecUser loggedInUser) {
     405                if (loggedInUser == null) {
     406                        return false;
     407                }
    437408
    438409                // Administrators are allowed to write every study
    439                 if( loggedInUser.hasAdminRights() ) {
     410                if (loggedInUser.hasAdminRights()) {
    440411                        return true;
    441412                }
    442413
    443         return this.owner == loggedInUser || this.writers.contains(loggedInUser)
    444     }
    445 
    446     /**
    447     * Returns true if the given user is the owner of this study
    448     */
    449     public boolean isOwner(SecUser loggedInUser) {
    450         if( loggedInUser == null ) {
    451             return false;
    452         }
    453         return this.owner == loggedInUser
    454     }
     414                return this.owner == loggedInUser || this.writers.contains(loggedInUser)
     415        }
     416
     417        /**
     418        * Returns true if the given user is the owner of this study
     419        */
     420        public boolean isOwner(SecUser loggedInUser) {
     421                if (loggedInUser == null) {
     422                        return false;
     423                }
     424                return this.owner == loggedInUser
     425        }
    455426
    456427        /**
     
    459430        public static giveWritableStudies(SecUser user, int max) {
    460431                // User that are not logged in, are not allowed to write to a study
    461                 if( user == null )
    462                         return [];
    463                        
     432                if (user == null)
     433                return [];
     434
    464435                def c = Study.createCriteria()
    465436
    466437                // Administrators are allowed to read everything
    467                 if( user.hasAdminRights() ) {
     438                if (user.hasAdminRights()) {
    468439                        return c.list {
    469440                                maxResults(max)
     
    474445                        maxResults(max)
    475446                        or {
    476                                 eq( "owner", user )
     447                                eq("owner", user)
    477448                                writers {
    478                                         eq( "id", user.id )
     449                                        eq("id", user.id)
    479450                                }
    480451                        }
     
    488459                def c = Study.createCriteria()
    489460
    490         // Administrators are allowed to read everything
    491                 if( user == null ) {
    492             return c.list {
     461                // Administrators are allowed to read everything
     462                if (user == null) {
     463                        return c.list {
    493464                                maxResults(max)
    494                 and {
    495                     eq( "published", true )
    496                     eq( "publicstudy", true )
    497                 }
    498             }
    499         } else if( user.hasAdminRights() ) {
    500             return c.list {
     465                                and {
     466                                        eq("published", true)
     467                                        eq("publicstudy", true)
     468                                }
     469                        }
     470                } else if (user.hasAdminRights()) {
     471                        return c.list {
    501472                                maxResults(max)
    502473                        }
    503                 } else  {
    504             return c.list {
     474                } else {
     475                        return c.list {
    505476                                maxResults(max)
    506                 or {
    507                     eq( "owner", user )
    508                     writers {
    509                         eq( "id", user.id )
    510                     }
    511                     and {
    512                         readers {
    513                             eq( "id", user.id )
    514                         }
    515                         eq( "published", true )
    516                     }
    517                 }
    518             }
    519         }
     477                                or {
     478                                        eq("owner", user)
     479                                        writers {
     480                                                eq("id", user.id)
     481                                        }
     482                                        and {
     483                                                readers {
     484                                                        eq("id", user.id)
     485                                                }
     486                                                eq("published", true)
     487                                        }
     488                                }
     489                        }
     490                }
    520491        }
    521492}
Note: See TracChangeset for help on using the changeset viewer.