Changeset 1175


Ignore:
Timestamp:
Nov 19, 2010, 11:51:09 AM (6 years ago)
Author:
robert@…
Message:

The templateeditor is now capable of adding new items to a stringlist (that is in use), or adding new ontologies to a ontologyterm field that is in use. See ticket #74

Location:
trunk/grails-app
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/studycapturing/TemplateEditorController.groovy

    r1159 r1175  
    401401                        def listEntries = [];
    402402                        params.listEntries.eachLine {
    403                                 // Search whether a listitem with this name already exists.
    404                                 // if it does, use that one to prevent pollution of the database
     403                                // We don't search for a listitem that might already exist,
     404                                // because if we use that list item, it will be removed from the
     405                                // other string list.
    405406                                def name = it.trim();
    406                                 def listitem = TemplateFieldListItem.findByName( name );7
    407                                 if( !listitem ) {
    408                                         listitem = new TemplateFieldListItem( name: name )
    409                                 }
     407
     408                                def listitem = new TemplateFieldListItem( name: name )
    410409                                listEntries.add( listitem );
    411410                        }
     
    466465
    467466                // If this field is type stringlist or ontology, we have to prepare the parameters
    468                 if( params.type.toString() == 'STRINGLIST' ) {
     467                //
     468                // For stringlist and ontologyterm fields, the list items can be changed, even when the field is in use
     469                // In that case, only never-used items can be removed or changed and items can be added. If that is the case
     470                // params.is_disabled is true and we should combine listEntries and extraListEntries with the items already in use.
     471                if( params.type.toString() == 'STRINGLIST' || ( templateField.type == TemplateFieldType.STRINGLIST && params.is_disabled) ) {
     472                        def listEntryLines = "";
    469473                        def listEntries = [];
    470                         params.listEntries.eachLine {
    471                                 // Search whether a listitem with this name already exists.
    472                                 // if it does, use that one to prevent pollution of the database
    473                                 def name = it.trim();
    474                                 def listitem = TemplateFieldListItem.findByName( name );7
    475                                 if( !listitem ) {
    476                                         listitem = new TemplateFieldListItem( name: name )
     474
     475                        if( params.is_disabled ) {
     476                                listEntries = templateField.getUsedListEntries();
     477                        }
     478
     479                        if( params.listEntries ) {
     480                                listEntryLines = params.listEntries;
     481                               
     482                                listEntryLines.eachLine {
     483                                        // We don't search for a listitem that might already exist,
     484                                        // because if we use that list item, it will be removed from the
     485                                        // other string list. We only search for an item that already
     486                                        // belongs to this list.
     487                                        def name = it.trim();
     488
     489                                        def c = TemplateFieldListItem.createCriteria()
     490                                        def listitem = c.get {
     491                                                eq( "name", name )
     492                                                eq( "parent", templateField)
     493                                        }
     494                                        if( !listitem ) {
     495                                                listitem = new TemplateFieldListItem( name: name )
     496                                        }
     497
     498                                        // Prevent using the same list entry twice
     499                                        if( !listEntries.contains( listitem ) )
     500                                                listEntries.add( listitem );
    477501                                }
    478                                 listEntries.add( listitem );
    479502                        }
    480503
     504                        // Add listEntries to the templateField
    481505                        params.listEntries = listEntries;
    482506                } else {
     
    485509
    486510                // If this field is a ontologyterm, we add ontology objects
    487                 if( params.type.toString() == 'ONTOLOGYTERM' && params.ontologies ) {
    488                         params.ontologies = Ontology.getAll( params.ontologies.collect { Integer.parseInt( it ) } );
     511                // For stringlist and ontologyterm fields, the list items can be changed, even when the field is in use
     512                // In that case, only never-used items can be removed or changed and items can be added. If that is the case
     513                // params.is_disabled is true and we should combine ontologies with the ontologies already in use.
     514                if( ( params.type.toString() == 'ONTOLOGYTERM' || ( templateField.type == TemplateFieldType.ONTOLOGYTERM && params.is_disabled ) ) && params.ontologies ) {
     515                        def usedOntologies = [];
     516
     517                        if( params.is_disabled ) {
     518                                usedOntologies = templateField.getUsedOntologies();
     519                        }
     520
     521                        if( params.ontologies ) {
     522                                def ontologies = params.ontologies;
     523       
     524                                params.ontologies = usedOntologies + Ontology.getAll( ontologies.collect { Integer.parseInt( it ) } );
     525                        }
     526
    489527                } else {
    490528                        params.remove( 'ontologies' );
    491529                }
    492530
     531                // A field that is already used in one or more templates, but is not filled everywhere,
     532                // can not be set to required
     533                if( params.required ) {
     534                        if( !templateField.isFilledInAllObjects() ) {
     535                                response.status = 500;
     536                                render "A field can only be marked as required if all objects using this field have a value for the field."
     537                                return
     538                        }
     539                }
     540
    493541                // Set all parameters
    494542                templateField.properties = params
     543
     544                templateField.validate();
     545               
     546
    495547        if (!templateField.hasErrors() && templateField.save(flush: true)) {
     548
     549                        // Remove all orphaned list items, because grails doesn't handle it for us
     550                        TemplateFieldListItem.findAllByParent( templateField ).each {
     551                                if( !params.listEntries.contains( it ) ) {
     552                                        templateField.removeFromListEntries( it );
     553                                        it.delete();
     554                                }
     555                        }
    496556
    497557                        // Select the template to use for the HTML output
     
    511571        } else {
    512572            response.status = 500;
    513             render 'TemplateField was not updated because errors occurred.';
     573            render 'TemplateField was not updated because errors occurred. Please contact the system administrator';
    514574            return
    515575        }
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy

    r1167 r1175  
    600600                        // iterate through ontologies and find term
    601601                        field.ontologies.each() { ontology ->
    602                                 def term = ontology.giveTermByName(value)
    603 
    604                                 // found a term?
    605                                 if (term) {
    606                                         value = term
    607                                 }
     602                                // If we've found a term already, value.class == Term. In that case,
     603                                // we shouldn't look further. Unfortunately, groovy doesn't support breaking out of
     604                                // each(), so we check it on every iteration.
     605                                if( value.class == String ) {
     606                                        def term = ontology.giveTermByName(value)
     607
     608                                        // found a term?
     609                                        if (term) {
     610                                                value = term
     611                                        }
     612                                }
     613                        }
     614
     615                        // If the term is not found in any ontology
     616                        if( value.class == String ) {
    608617                                // TODO: search ontology for the term online (it may still exist) and insert it into the Term cache
    609618                                // if not found, throw exception
    610                                 else {
    611                                         throw new IllegalArgumentException("Ontology term not recognized (not in the GSCF ontology cache): ${value} when setting field ${fieldName}")
    612                                 }
     619                                throw new IllegalArgumentException("Ontology term not recognized (not in the GSCF ontology cache): ${value} when setting field ${fieldName}")
    613620                        }
    614621                }
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateField.groovy

    r1160 r1175  
    7676                entity column:"templatefieldentity"
    7777                unit column:"templatefieldunit"
    78                 comment column:"templatefieldcomment"               
     78                comment column:"templatefieldcomment"
    7979        }
    8080
     
    109109
    110110        /**
     111         * Retrieves all list items of a stringlist template field that have been used in an object
     112         *
     113         * @return      ArrayList containing all list items of this template field that have been used in an object.
     114         */
     115        def getUsedListEntries() {
     116                if( this.type != TemplateFieldType.STRINGLIST )
     117                        return []
     118
     119                return this.listEntries.findAll { this.entryUsed( it ) }
     120        }
     121
     122        /**
     123         * Retrieves all list items of a stringlist template field that have never been used in an object
     124         *
     125         * @return      ArrayList containing all list items of this template field that have nevert been used in an object.
     126         */
     127        def getNonUsedListEntries() {
     128                if( this.type != TemplateFieldType.STRINGLIST )
     129                        return []
     130               
     131                return this.listEntries.findAll { !this.entryUsed( it ) }
     132        }
     133
     134        /**
     135         * Retrieves all ontologies of an ontologyterm template field that have been used in an object
     136         *
     137         * @return      ArrayList containing all ontologies of this template field that have been used in an object
     138         *                      (i.e. all ontologies from which a term has been selected in this template field).
     139         */
     140        def getUsedOntologies() {
     141                if( this.type != TemplateFieldType.ONTOLOGYTERM )
     142                        return []
     143
     144                return this.ontologies.findAll { this.entryUsed( it ) }
     145        }
     146
     147        /**
     148         * Retrieves all list items of an ontologyterm template field that have never been used in an object
     149         *
     150         * @return      ArrayList containing all ontologies of this template field that have never been used in an object.
     151         *                      (i.e. all ontologies from which no term has been selected in this template field).
     152         */
     153        def getNonUsedOntologies() {
     154                if( this.type != TemplateFieldType.ONTOLOGYTERM )
     155                        return []
     156
     157                return this.ontologies.findAll { !this.entryUsed( it ) }
     158        }
     159
     160        /**
    111161         * Checks whether this template field is used in a template
    112162         *
     
    151201         */
    152202        def isFilled() {
    153                 // Find all entities that use this template
     203                // Find all templates that use this template field
    154204                def templates = getUses();
    155205
     
    157207                        return false;
    158208
     209                // Find all entities that use these templates
    159210                def c = this.entity.createCriteria()
    160211                def entities = c {
     
    186237
    187238                return filledEntities.size() > 0;
     239        }
     240
     241        /**
     242         * Checks whether this template field is filled in all objects using a template with this template field
     243         * If the template field is never used, the method returns true. If the template field is used in a template,
     244         * but no objects with this template exist, the method also returns true
     245         *
     246         * @returns             false iff objects exist using this template field, but without a value for this field. true otherwise
     247         */
     248        def isFilledInAllObjects() {
     249                // Find all templates that use this entity
     250                def templates = getUses();
     251
     252                if( templates.size() == 0 )
     253                        return true;
     254
     255                // Find all entities that use these templates
     256                def c = this.entity.createCriteria()
     257                def entities = c {
     258                        'in'("template",templates)
     259                }
     260
     261                if( entities.size() == 0 )
     262                        return true;
     263
     264                def emptyEntities = entities.findAll { entity -> !entity.getFieldValue( this.name ) }
     265
     266                return ( emptyEntities.size() == 0 );
    188267        }
    189268
     
    211290         */
    212291        def entryUsed(TemplateFieldListItem item) {
    213                 //return numUses() > 0;
     292                if( this.type != TemplateFieldType.STRINGLIST )
     293                        return false;
     294
     295                // Find all templates that use this template field
     296                def templates = getUses();
     297
     298                if( templates.size() == 0 )
     299                        return false;
     300
     301                // Find all entities that use these templates
     302                def c = this.entity.createCriteria()
     303                def entities = c {
     304                        'in'("template",templates)
     305                }
     306
     307                if( entities.size() == 0 )
     308                        return false
     309                       
     310                def entitiesWithListItem = entities.findAll { entity -> entity.getFieldValue( this.name ).equals( item ) }
     311
     312                return entitiesWithListItem.size() > 0;
    214313        }
    215314
     
    220319         * @returns                     true iff the ontology is part of this template field and a term from the given
    221320         *                                      ontology is selected in an entity where this template field is used. false otherwise
    222          *                                      Returns false if the type of this template field is other than ONTOLOGY
     321         *                                      Returns false if the type of this template field is other than ONTOLOGYTERM
    223322         */
    224323        def entryUsed(Ontology item) {
    225                 //return numUses() > 0;
     324                if( this.type != TemplateFieldType.ONTOLOGYTERM )
     325                        return false;
     326
     327                // Find all templates that use this template field
     328                def templates = getUses();
     329
     330                // If the template field is never used in a template, it will also never
     331                // be filled, and this Ontology will never be used
     332                if( templates.size() == 0 )
     333                        return false;
     334
     335                // Find all entities that use these templates
     336                def c = this.entity.createCriteria()
     337                def entities = c {
     338                        'in'("template",templates)
     339                }
     340
     341                if( entities.size() == 0 )
     342                        return false
     343
     344                def entitiesWithOntology = entities.findAll { entity ->
     345                        def value = entity.getFieldValue( this.name );
     346                        if( value )
     347                                return value.ontology.equals( item )
     348                        else
     349                                return false;
     350                }
     351
     352                return entitiesWithOntology.size() > 0;
    226353        }
    227354
  • trunk/grails-app/views/templateEditor/elements/_disabledFieldForm.gsp

    r959 r1175  
     1        <g:hiddenField name="id" value="${templateField?.id}" />
     2        <g:hiddenField name="version" value="${templateField?.version}" />
     3        <g:hiddenField name="is_disabled" value="1" />
     4        <g:if test="${is_selected}"><g:hiddenField name="renderTemplate" value="selected" /></g:if>
     5        <g:if test="${template}"><g:hiddenField name="templateId" value="${template.id}" /></g:if>
     6
    17        <label for="name">Name:</label> <g:textField disabled="disabled" name="name" value="${templateField?.name}" /><br />
    28        <label for="type">Type:</label> <g:textField disabled="disabled" name="type" value="${templateField?.type}" /><br />
    39
    410        <div class="extra stringlist_options" <g:if test="${templateField?.type.toString() == 'STRINGLIST'}">style='display: block;'</g:if>>
    5           <label for="type">Items:</label>
    6                 <g:textArea name="listEntries" disabled="disabled" value="${templateField?.listEntries?.name?.join( '\n' )}" />
     11          <label for="type">Used items:</label>
     12                <g:textArea name="usedListEntries" disabled="disabled" value="${templateField?.getUsedListEntries().name?.join( '\n' )}" />
     13          <label for="type">Extra Items (every item on a new line):</label>
     14                <g:textArea name="listEntries" value="${templateField?.getNonUsedListEntries().name?.join( '\n' )}" />
    715        </div>
    816        <div class="extra ontologyterm_options" <g:if test="${templateField?.type.toString() == 'ONTOLOGYTERM'}">style='display: block;'</g:if>>
    9           <label for="type">Ontology:</label> <g:textArea name="ontology" disabled="disabled" value="${templateField?.ontologies?.name?.join( '\n' )}" /><br />
     17          <label for="type">Used ontologies:</label> <g:textArea name="ontology" disabled="disabled" value="${templateField?.getUsedOntologies().name?.join( '\n' )}" /><br />
     18
     19          <label for="type">Extra ontologies:<br /><br /><a href="#" style="text-decoration: underline;" onClick="openOntologyDialog();">Add new</a></label>
     20                <g:select multiple="yes" size="5" from="${ontologies - templateField?.getUsedOntologies()}" class="ontologySelect" optionValue="name" optionKey="id" name="ontologies" id="ontologies_${templateField?.id}" value="${templateField?.getNonUsedOntologies()}" /><br />
     21
    1022        </div>
    1123       
     
    1325        <label for="comment">Comment:</label> <g:textArea disabled="disabled" name="comment" value="${templateField?.comment}" /><br />
    1426        <label for="required">Required:</label> <input type="checkbox" disabled <g:if test="${templateField?.required}">checked</g:if><br />
     27
     28        <div class="templateFieldButtons">
     29          <g:if test="${ templateField?.type.toString() == 'STRINGLIST' || templateField?.type.toString() == 'ONTOLOGYTERM' }">
     30                <input type="button" value="Save" onClick="updateTemplateField( ${templateField?.id} );">
     31                <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField?.id} );">
     32          </g:if>
     33          <g:else>
     34                <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField?.id} );">
     35          </g:else>
     36        </div>
  • trunk/grails-app/views/templateEditor/elements/_fieldForm.gsp

    r1056 r1175  
    1         <label for="name">Name:</label> <g:textField name="name" value="${templateField?.name}" /><br />
     1  <g:hiddenField name="id" value="${templateField?.id}" />
     2  <g:hiddenField name="version" value="${templateField?.version}" />
     3  <g:if test="${is_new}"><g:hiddenField name="entity" value="${encryptedEntity}" /></g:if>
     4  <g:if test="${is_selected}"><g:hiddenField name="renderTemplate" value="selected" /></g:if>
     5  <g:if test="${template}"><g:hiddenField name="templateId" value="${template.id}" /></g:if>
     6<label for="name">Name:</label> <g:textField name="name" value="${templateField?.name}" /><br />
    27        <label for="type">Type:</label>
    38          <%
     
    3742        <label for="comment">Comment:</label> <g:textArea name="comment" value="${templateField?.comment}" /><br />
    3843        <label for="required">Required:</label> <g:checkBox name="required" value="${templateField?.required}" /><br />
     44
     45        <div class="templateFieldButtons">
     46          <g:if test="${is_new}">
     47                <input type="button" value="Save" onClick="createTemplateField( 'new' );">
     48                <input type="button" value="Cancel" onClick="hideTemplateFieldForm( 'new' );">
     49          </g:if>
     50          <g:else>
     51                <input type="button" value="Save" onClick="updateTemplateField( ${templateField?.id} );">
     52                <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField?.id} );">
     53          </g:else>
     54        </div>
  • trunk/grails-app/views/templateEditor/elements/_liFieldInUse.gsp

    r1159 r1175  
    1010   
    1111<form class="templateField_form" id="templateField_${templateField.id}_form" action="updateField">
    12         <g:hiddenField name="id" value="${templateField.id}" />
    13         <g:hiddenField name="version" value="${templateField.version}" />
    14         <p class="noEditsPossible">Editing not possible. Field is used in ${numUses} template(s).</p>
    15         <g:render template="elements/disabledFieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/>
    16         <div class="templateFieldButtons">
    17                 <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );">
    18         </div>
     12  <g:if test="${ templateField?.type.toString() == 'STRINGLIST' }">
     13    <p class="noEditsPossible">You can only add or remove list items that are not used. Field is used in ${numUses} template(s).</p>
     14  </g:if>
     15  <g:else>
     16    <g:if test="${templateField?.type.toString() == 'ONTOLOGYTERM' }">
     17    <p class="noEditsPossible">You can only add or remove ontologies that are not used. Field is used in ${numUses} template(s).</p>
     18        </g:if>
     19        <g:else>
     20          <p class="noEditsPossible">Editing not possible. Field is used in ${numUses} template(s).</p>
     21        </g:else>
     22  </g:else>
     23  <g:render template="elements/disabledFieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/>
    1924</form>
    2025
  • trunk/grails-app/views/templateEditor/elements/_liFieldNotInUse.gsp

    r1159 r1175  
    99
    1010<form class="templateField_form" id="templateField_${templateField.id}_form" action="updateField">
    11         <g:hiddenField name="id" value="${templateField.id}" />
    12         <g:hiddenField name="version" value="${templateField.version}" />
    1311        <g:render template="elements/fieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/>
    14         <div class="templateFieldButtons">
    15                 <input type="button" value="Save" onClick="updateTemplateField( ${templateField.id} );">
    16                 <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );">
    17         </div>
    1812</form>
  • trunk/grails-app/views/templateEditor/elements/_liFieldSelected.gsp

    r1159 r1175  
    1515  <form class="templateField_form" id="templateField_${templateField.id}_form" action="updateField">
    1616          <g:if test="${templateField.isEditable()}">
    17                 <g:hiddenField name="id" value="${templateField.id}" />
    18                 <g:hiddenField name="version" value="${templateField.version}" />
    19                 <g:hiddenField name="renderTemplate" value="selected" />
    20                 <g:hiddenField name="templateId" value="${template.id}" />
    21                 <g:render template="elements/fieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/>
    22                 <div class="templateFieldButtons">
    23                         <input type="button" value="Save" onClick="updateTemplateField( ${templateField.id} );">
    24                         <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );">
    25                 </div>
     17                <g:render template="elements/fieldForm" model="['templateField': templateField, 'template': template, 'is_selected': true, 'ontologies': ontologies, 'fieldTypes': fieldTypes]" />
    2618          </g:if>
    2719        <g:else>
    28                 <g:render template="elements/disabledFieldForm" model="['templateField': templateField, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/>
    29                 <div class="templateFieldButtons">
    30                         <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );">
    31                 </div>
     20                <g:render template="elements/disabledFieldForm" model="['templateField': templateField, 'template': template, 'is_selected': true, 'ontologies': ontologies, 'fieldTypes': fieldTypes]"/>
    3221        </g:else>
    3322  </form>
  • trunk/grails-app/views/templateEditor/template.gsp

    r1153 r1175  
    112112
    113113                                        <form class="templateField_form" id="templateField_new_form" action="createField">
    114                                                 <g:hiddenField name="entity" value="${encryptedEntity}" />
    115                                                 <g:render template="elements/fieldForm" model="['templateField': null, 'fieldTypes': fieldTypes]"/>
    116                                                 <div class="templateFieldButtons">
    117                                                         <input type="button" value="Save" onClick="createTemplateField( 'new' );">
    118                                                         <input type="button" value="Cancel" onClick="hideTemplateFieldForm( 'new' );">
    119                                                 </div>
     114                                                <g:render template="elements/fieldForm" model="['templateField': null, 'fieldTypes': fieldTypes, 'encryptedEntity': encryptedEntity, 'is_new': true]"/>
    120115                                        </form>
    121116                                </div>
Note: See TracChangeset for help on using the changeset viewer.