Changeset 1277


Ignore:
Timestamp:
Dec 16, 2010, 3:42:15 PM (6 years ago)
Author:
t.w.abma@…
Message:
  • rewrite of the Importer Wizard into an Ajaxflow
Location:
trunk
Files:
20 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/importer/ImporterController.groovy

    r1223 r1277  
     1package dbnp.importer
     2import dbnp.studycapturing.Study
     3import dbnp.studycapturing.Template
     4
     5import org.apache.poi.ss.usermodel.Workbook
     6
     7import grails.converters.JSON
     8import cr.co.arquetipos.crypto.Blowfish
     9
     10
    111/**
    2  * Importer controller
     12 * Wizard Controller
    313 *
    4  * The importer controller handles the uploading of tabular, comma delimited and Excel format
    5  * based files. When uploaded a preview is shown of the data and the user can adjust the column
    6  * type. Data in cells which don't correspond to the specified column type will be represented as "#error".
    7  *
    8  * The importer controller catches the actions and consecutively performs the
    9  * logic behind it.
    10  *
    11  * @package     importer
    12  * @author      t.w.abma@umcutrecht.nl
    13  * @since       20100126
     14 * @author      Jeroen Wesbeek
     15 * @since       20101206
    1416 *
    1517 * Revision information:
     
    1820 * $Date$
    1921 */
    20 
    21 package dbnp.importer
    22 
    23 import dbnp.studycapturing.Template
    24 import dbnp.studycapturing.Study
    25 
    26 import dbnp.studycapturing.TemplateFieldType
    27 import grails.converters.JSON
    28 import org.apache.poi.ss.usermodel.Workbook
    29 import grails.plugins.springsecurity.Secured
    30 
    31 import cr.co.arquetipos.crypto.Blowfish
    32 
    33 @Secured(['IS_AUTHENTICATED_REMEMBERED'])
    3422class ImporterController {
     23    // the pluginManager is used to check if the Grom
     24    // plugin is available so we can 'Grom' development
     25    // notifications to the unified notifications daemon
     26    // (see http://www.grails.org/plugin/grom)
     27    def pluginManager
     28    def AuthenticationService
     29    def fileService
    3530    def ImporterService
    36     def AuthenticationService
    37 
    38     /**
    39      * Default page
    40      **/
    41 
     31       
     32    /**
     33     * index method, redirect to the webflow
     34     * @void
     35     */
    4236    def index = {
    43         // no data has been imported yet
    44         session.import_wizard_init = true
    45 
    46         // should do a check what is in the url, strip it?
    47         session.import_referer = params.redirectTo
    48 
    49         grailsApplication.config.gscf.domain.importableEntities.each {           
    50             it.value.encrypted =
    51                                 Blowfish.encryptBase64(
    52                                         it.value.entity.toString().replaceAll(/^class /, ''),
    53                                         grailsApplication.config.crypto.shared.secret
    54                                 )
    55         }
    56 
    57         render(view:"index_simple",
    58                model:[studies:Study.findAllWhere(owner:AuthenticationService.getLoggedInUser()),
    59                entities: grailsApplication.config.gscf.domain.importableEntities])
    60     }
    61 
    62     def simpleWizard = {
    63         //render(view:"index_simple", model:[studies:Study.findAllWhere(owner:AuthenticationService.getLoggedInUser()), entities: grailsApplication.config.gscf.domain.importableEntities])
    64     }
    65 
    66     def advancedWizard = {
    67         //render(view:"index_advanced", model:[templates:Template.list()])
    68     }
    69 
    70     /**
    71     * This method will move the uploaded file to a temporary path and send the header
    72     * and the first n rows to the preview
    73     * @param importfile uploaded file to import
    74     * @param study.id study identifier
    75     */
    76     def upload_advanced = {
    77         def wb = handleUpload('importfile')
    78 
    79         session.importer_header = ImporterService.getHeader(wb, 0)
    80         session.importer_study = Study.get(params.study.id.toInteger())
    81         session.importer_template_id = params.template_id
    82         session.importer_workbook = wb
    83 
    84         render (view:"step1_advanced", model:[header:session.importer_header, datamatrix:ImporterService.getDatamatrix(wb, session.importer_header, 0, 5)])
    85     }
    86 
    87     /**
    88     * This method will move the uploaded file to a temporary path and send the header
    89     * and the rows to the postview
    90     *
    91     * @param importfile uploaded file to import
    92     * @param entity string representation of the entity chosen
    93     */
    94     def upload_simple = {
    95         def wb = handleUpload('importfile')
    96         def selectedentities = []
    97         //def entity = grailsApplication.config.gscf.domain.importableEntities.get(params.entity).entity
     37        // Grom a development message
     38        if (pluginManager.getGrailsPlugin('grom')) "redirecting into the webflow".grom()
     39
     40        // encrypt the importable entities
     41        grailsApplication.config.gscf.domain.importableEntities.each {
     42            it.value.encrypted =
     43            Blowfish.encryptBase64(
     44                it.value.entity.toString().replaceAll(/^class /, ''),
     45                grailsApplication.config.crypto.shared.secret
     46            )
     47        }
     48
     49        /**
     50         * Do you believe it in your head?
     51         * I can go with the flow
     52         * Don't say it doesn't matter (with the flow) matter anymore
     53         * I can go with the flow (I can go)
     54         * Do you believe it in your head?
     55         */
     56        redirect(action: 'pages')
     57    }
     58
     59    /**
     60     * WebFlow definition
     61     * @void
     62     */
     63    def pagesFlow = {
     64        // start the flow
     65        onStart {
     66            // Grom a development message
     67            if (pluginManager.getGrailsPlugin('grom')) "entering the WebFlow".grom()
     68
     69            // define variables in the flow scope which is availabe
     70            // throughout the complete webflow also have a look at
     71            // the Flow Scopes section on http://www.grails.org/WebFlow
     72            //
     73            // The following flow scope variables are used to generate
     74            // wizard tabs. Also see common/_tabs.gsp for more information
     75            flow.page = 0
     76            flow.pages = [
     77                [title: 'Import file'],
     78                [title: 'Properties'],
     79                [title: 'Mappings'],
     80                [title: 'Imported'],
     81                [title: 'Persist']
     82            ]
     83            flow.cancel = true;
     84            flow.quickSave = true;
     85
     86            success()
     87        }
     88
     89        // render the main wizard page which immediately
     90        // triggers the 'next' action (hence, the main
     91        // page dynamically renders the study template
     92        // and makes the flow jump to the study logic)
     93        mainPage {
     94            render(view: "/importer/index")
     95            onRender {
     96                // Grom a development message
     97                if (pluginManager.getGrailsPlugin('grom')) "rendering the main Ajaxflow page (index.gsp)".grom()
     98               
     99                // let the view know we're in page 1
     100                flow.page = 1
     101                success()
     102            }
     103            on("next").to "pageOne"
     104        }
     105
     106        // File import and entitie template selection page
     107        pageOne {
     108            render(view: "_page_one")
     109            onRender {
     110                log.info ".entering import wizard"
     111                // Grom a development message
     112                if (pluginManager.getGrailsPlugin('grom')) ".rendering the partial: pages/_page_one.gsp".grom()
     113
     114                flow.page = 1
     115                flow.studies = Study.findAllWhere(owner:AuthenticationService.getLoggedInUser())
     116                flow.importer_importableentities = grailsApplication.config.gscf.domain.importableEntities
     117               
     118                success()
     119            }
     120            on("next") {
     121                if (fileImportPage(flow, params)) {                   
     122                    success()
     123                } else {
     124                    println "field is missing"
     125                    error()
     126                }
     127                // put your bussiness logic (if applicable) in here
     128            }.to "pageTwo"
     129            on("toPageTwo") {
     130                // put your bussiness logic (if applicable) in here
     131            }.to "pageTwo"
     132            on("toPageThree") {
     133                // put your bussiness logic (if applicable) in here
     134            }.to "pageThree"
     135            on("toPageFour") {
     136                // put your bussiness logic (if applicable) in here
     137            }.to "pageFour"
     138            on("toPageFive") {
     139                // put your bussiness logic (if applicable) in here
     140                flow.page = 5
     141            }.to "save"
     142        }
     143
     144        // Property to column assignment page
     145        pageTwo {           
     146            render(view: "_page_two")
     147            onRender {
     148                log.info ".import wizard properties page"
     149                // Grom a development message
     150                if (pluginManager.getGrailsPlugin('grom')) ".rendering the partial: pages/_page_two.gsp".grom()
     151               
     152                flow.page = 2
     153                success()
     154            }
     155            on("next") {
     156                if (propertiesPage(flow, params)) {
     157                    success()
     158                } else {
     159                    println "properties are wrong"
     160                    error()
     161                }
     162            }.to "pageThree"
     163            on("previous").to "pageOne"
     164            on("toPageOne").to "pageOne"
     165            on("toPageThree").to "pageThree"
     166            on("toPageFour").to "pageFour"
     167            on("toPageFive") {
     168                flow.page = 5
     169            }.to "save"
     170        }
     171
     172        // Mapping page
     173        pageThree {           
     174            render(view: "_page_three")
     175            onRender {               
     176                log.info ".import wizard mapping page"
     177                // Grom a development message
     178                if (pluginManager.getGrailsPlugin('grom')) ".rendering the partial pages/_page_three.gsp".grom()
     179
     180                flow.page = 3
     181                success()
     182            }           
     183            on("refresh") {               
     184                    success()
     185            }.to "pageThree"
     186            on("next") {
     187                if (mappingsPage(flow, params)) {
     188                    success()
     189                } else {
     190                    log.error ".import wizard mapping error, could not validate all entities"
     191                    error()                   
     192                }
     193            }.to "pageFour"
     194            on("previous").to "pageTwo"
     195            on("toPageOne").to "pageOne"
     196            on("toPageTwo").to "pageTwo"
     197            on("toPageFour").to "pageFour"
     198            on("toPageFive") {
     199                flow.page = 5
     200            }.to "save"
     201        }
     202
     203        // Imported data overview page
     204        pageFour {
     205            render(view: "_page_four")
     206            onRender {
     207                // Grom a development message
     208                if (pluginManager.getGrailsPlugin('grom')) ".rendering the partial pages/_page_four.gsp".grom()
     209
     210                flow.page = 4
     211                success()
     212            }
     213            on("next") {
     214                if (importedPage(flow, params)) {
     215                    success()
     216                } else {
     217                    log.error ".import wizard imported error, something went wrong showing the imported entities"
     218                    error()
     219                }
     220                flow.page = 5
     221            }.to "save"
     222            on("previous").to "pageThree"
     223            on("toPageOne").to "pageOne"
     224            on("toPageTwo").to "pageTwo"
     225            on("toPageThree").to "pageThree"
     226            on("toPageFive") {
     227                flow.page = 5
     228            }.to "save"
     229        }
     230
     231        // Save the imported data
     232        save {
     233            action {
     234                // here you can validate and save the
     235                // instances you have created in the
     236                // ajax flow.
     237                try {
     238                    // Grom a development message
     239                    if (pluginManager.getGrailsPlugin('grom')) ".persisting instances to the database...".grom()                   
     240
     241                    if (saveEntities(flow, params)) {
     242                        println "succes"
     243                        success()
     244                    } else {
     245                        log.error ".import wizard imported error, something went wrong showing the imported entities"                       
     246                        //throw Exception
     247                    }                   
     248                } catch (Exception e) {
     249                    // put your error handling logic in
     250                    // here                   
     251                    flow.page = 4
     252                    error()
     253                }
     254            }
     255            on("error").to "error"
     256            on(Exception).to "error"
     257            on("success").to "finalPage"
     258        }
     259
     260        // render errors
     261        error {
     262            render(view: "_error")
     263            onRender {
     264               
     265                // Grom a development message
     266                if (pluginManager.getGrailsPlugin('grom')) ".rendering the partial pages/_error.gsp".grom()
     267
     268                // set page to 4 so that the navigation
     269                // works (it is disabled on the final page)
     270                flow.page = 4
     271            }
     272            on("next").to "save"
     273            on("previous").to "pageFour"
     274            on("toPageOne").to "pageOne"
     275            on("toPageTwo").to "pageTwo"
     276            on("toPageThree").to "pageThree"
     277            on("toPageFour").to "pageFour"
     278            on("toPageFive").to "save"
     279
     280        }
     281
     282        // last wizard page
     283        finalPage {
     284            render(view: "_final_page")
     285            onRender {
     286                // Grom a development message
     287                if (pluginManager.getGrailsPlugin('grom')) ".rendering the partial pages/_final_page.gsp".grom()
     288                               
     289                success()
     290            }
     291        }
     292    }
     293
     294    /**
     295     * Return templates which belong to a certain entity type
     296     *
     297     * @param entity entity name string (Sample, Subject, Study et cetera)
     298     * @return JSON object containing the found templates
     299     */
     300    def ajaxGetTemplatesByEntity = {
    98301        def entityName = Blowfish.decryptBase64(
    99                             params.entity,
    100                             grailsApplication.config.crypto.shared.secret
    101                          )
    102 
    103         def entityClass = Class.forName(entityName, true, this.getClass().getClassLoader())
    104        
    105         // Initialize some session variables
    106         session.importer_workbook = wb
    107         session.importer_study = Study.get(params.study.id.toInteger())
    108 
    109         // Is the current logged in user allowed to write to this study?
    110         if (session.importer_study.canWrite(AuthenticationService.getLoggedInUser())) {
    111             session.importer_template_id = params.template_id
    112             session.importer_sheetindex = params.sheetindex.toInteger() -1 // 0 == first sheet
    113             session.importer_datamatrix_start = params.datamatrix_start.toInteger() -1 // 0 == first row
    114             session.importer_headerrow = params.headerrow.toInteger()
    115 
    116             // Get the header from the Excel file using the arguments given in the first step of the wizard
    117             session.importer_header = ImporterService.getHeader(wb,
    118                                                                 session.importer_sheetindex,
    119                                                                 session.importer_headerrow,
    120                                                                 session.importer_datamatrix_start,
    121                                                                 entityClass)
    122        
    123             // Initialize 'selected entities', used to show entities above the columns
    124             session.importer_header.each {               
    125                 selectedentities.add([name:entityName, columnindex:it.key.toInteger()])
    126             }
    127 
    128             def templates = Template.get(session.importer_template_id)
    129 
    130             render(view:"step2_simple", model:[entities: selectedentities,
    131                                         header:session.importer_header,
    132                                         datamatrix:ImporterService.getDatamatrix(
    133                                         wb, session.importer_header,
    134                                         session.importer_sheetindex,
    135                                         session.importer_datamatrix_start,
    136                                         5),
    137                                         templates:templates])
    138         } // end of if
    139         else {
    140             render (template:"common/error",
    141                     model:[error:"Wrong permissions: you are not allowed to write to the study you selected (${session.importer_study})."])
    142         }
    143     }
    144 
    145     /**
    146      * This method handles a file being uploaded and storing it in a temporary directory
    147      * and returning a workbook
     302            params.entity,
     303            grailsApplication.config.crypto.shared.secret
     304        )
     305
     306        //def entityClass = grailsApplication.config.gscf.domain.importableEntities.get(params.entity).entity
     307        def entityClass = entityName
     308
     309        // fetch all templates for a specific entity
     310        def templates = Template.findAllByEntity(Class.forName(entityClass, true, this.getClass().getClassLoader()))
     311
     312        // render as JSON
     313        render templates as JSON
     314    }
     315
     316    /**
     317     * Handle the file import page.
    148318     *
    149      * @param formfilename name used for the file field in the form
    150      * @return workbook object reference
    151      */
    152     private Workbook handleUpload(formfilename) {
    153 
    154         def downloadedfile = request.getFile(formfilename);
    155         def tempfile = new File(System.getProperty('java.io.tmpdir') + File.separatorChar + System.currentTimeMillis() + ".nmcdsp")
    156         downloadedfile.transferTo(tempfile)
    157 
    158         return ImporterService.getWorkbook(new FileInputStream(tempfile))
    159     }
    160 
    161     /**
    162      * Method to save the missing properties.
     319     * @param Map LocalAttributeMap (the flow scope)
     320     * @param Map GrailsParameterMap (the flow parameters = form data)
     321     * @returns boolean true if correctly validated, otherwise false
     322     */
     323    boolean fileImportPage(flow, params) {
     324        def importedfile = fileService.get(params['importfile'])
     325        //fileService.delete(YourFile)
     326
     327        if (params.entity && params.template_id && importedfile.exists()) {
     328            // create a workbook instance of the file
     329            session.importer_workbook = ImporterService.getWorkbook(new FileInputStream(importedfile))
     330           
     331            def selectedentities = []
     332           
     333            def entityName = Blowfish.decryptBase64(
     334                params.entity,
     335                grailsApplication.config.crypto.shared.secret
     336            )
     337           
     338            def entityClass = Class.forName(entityName, true, this.getClass().getClassLoader())
     339           
     340            // Initialize some session variables
     341            //flow.importer_workbook = wb // workbook object must be serialized for this to work
     342            flow.importer_study = Study.get(params.study.id.toInteger())           
     343
     344             // Is the current logged in user allowed to write to this study?
     345             if (flow.importer_study.canWrite(AuthenticationService.getLoggedInUser())) {
     346                flow.importer_template_id = params.template_id
     347                flow.importer_sheetindex = params.sheetindex.toInteger() -1 // 0 == first sheet
     348                flow.importer_datamatrix_start = params.datamatrix_start.toInteger() -1 // 0 == first row
     349                flow.importer_headerrow = params.headerrow.toInteger()
     350
     351                // Get the header from the Excel file using the arguments given in the first step of the wizard
     352                flow.importer_header = ImporterService.getHeader(session.importer_workbook,
     353                    flow.importer_sheetindex,
     354                    flow.importer_headerrow,
     355                    flow.importer_datamatrix_start,
     356                    entityClass)
     357
     358                // Initialize 'selected entities', used to show entities above the columns
     359                flow.importer_header.each {
     360                    selectedentities.add([name:entityName, columnindex:it.key.toInteger()])
     361                }
     362               
     363                flow.importer_selectedentities = selectedentities               
     364
     365                session.importer_datamatrix = ImporterService.getDatamatrix(
     366                            session.importer_workbook, flow.importer_header,
     367                            flow.importer_sheetindex,
     368                            flow.importer_datamatrix_start,
     369                            5)
     370
     371             
     372                flow.importer_templates = Template.get(flow.importer_template_id)
     373                flow.importer_allfieldtypes = "true"
     374            } // end of if
     375            /*else {
     376                render (template:"common/error",
     377                    model:[error:"Wrong permissions: you are not allowed to write to the study you selected (${flow.importer_study})."])
     378            }*/
     379
     380            return true
     381        }
     382    }
     383
     384    /**
     385     * Handle the property mapping page.
    163386     *
    164      * @param entity entity class we are using (dbnp.studycapturing.Subject etc.)
    165      */
    166 
    167     def saveMissingProperties = {       
     387     * @param Map LocalAttributeMap (the flow scope)
     388     * @param Map GrailsParameterMap (the flow parameters = form data)
     389     * @returns boolean true if correctly validated, otherwise false
     390     */
     391    boolean propertiesPage (flow, params) {
     392        // Find actual Template object from the chosen template name
     393        def template = Template.get(flow.importer_template_id)
     394
     395        params.columnproperty.index.each { columnindex, property ->
     396            // Create an actual class instance of the selected entity with the selected template
     397            // This should be inside the closure because in some cases in the advanced importer, the fields can have different target entities
     398            def entityClass = Class.forName(flow.importer_header[columnindex.toInteger()].entity.getName(), true, this.getClass().getClassLoader())
     399            def entityObj = entityClass.newInstance(template:template)
     400
     401            // Store the selected property for this column into the column map for the ImporterService
     402            flow.importer_header[columnindex.toInteger()].property = property
     403
     404            // Look up the template field type of the target TemplateField and store it also in the map
     405            flow.importer_header[columnindex.toInteger()].templatefieldtype = entityObj.giveFieldType(property)
     406
     407            // Is a "Don't import" property assigned to the column?
     408            flow.importer_header[columnindex.toInteger()].dontimport = (property=="dontimport") ? true : false
     409
     410            //if it's an identifier set the mapping column true or false
     411            entityObj.giveFields().each {
     412                (it.preferredIdentifier && (it.name==property)) ? flow.importer_header[columnindex.toInteger()].identifier = true : false
     413            }
     414        }
     415
     416        // Import the workbook and store the table with entity records and store the failed cells
     417        def (table, failedcells) = ImporterService.importData(flow.importer_template_id,
     418                                                              session.importer_workbook,
     419                                                              flow.importer_sheetindex,
     420                                                              flow.importer_datamatrix_start,
     421                                                              flow.importer_header)
     422
     423        flow.importer_importeddata = table
     424        flow.importer_failedcells = failedcells
     425    }
     426
     427    /**
     428     * Handle the mapping page.
     429     *
     430     * @param Map LocalAttributeMap (the flow scope)
     431     * @param Map GrailsParameterMap (the flow parameters = form data)
     432     * @returns boolean true if correctly validated, otherwise false
     433     */
     434    boolean mappingsPage(flow,params) {
    168435        def fielderrors = 0
    169         def invalidentities = 0
    170        
    171         session.importer_importeddata.each { table ->
    172             table.each { entity ->
     436        flow.importer_invalidentities = 0
     437
     438        flow.importer_importeddata.each { table ->
     439            table.each { entity ->
    173440                // a new entity is being traversed, if a field cannot be set, increase this counter
    174441                fielderrors = 0
    175442
    176                 entity.giveFields().each { field ->                   
     443                entity.giveFields().each { field ->
    177444                    try {
    178445                        // try to set the value
    179                         entity.setFieldValue (field.toString(), params["entity_" + entity.getIdentifier() + "_" + field.escapedName()])                       
    180                     } catch (Exception e) {                   
     446                        entity.setFieldValue (field.toString(), params["entity_" + entity.getIdentifier() + "_" + field.escapedName()])
     447                    } catch (Exception e) {
    181448                        fielderrors++
    182449                    }
    183                 }
     450                }
    184451
    185452                // a field could not be set in the entity, so the entity failed (is not validated)
    186                 if (fielderrors) invalidentities++
     453                if (fielderrors) flow.importer_invalidentities++
    187454
    188455                // all fields in the entity could be set, no errors, so remove it from the failed cells
    189456                if (!fielderrors) {
    190                      session.importer_failedcells.each { record ->
     457                    flow.importer_failedcells.each { record ->
    191458                        record.importcells.each { cell ->
    192                            // remove the cell from the failed cells session
    193                            if (cell.entityidentifier == entity.getIdentifier()) {                           
    194                                record.removeFromImportcells(cell)
    195                            }
     459                            // remove the cell from the failed cells session
     460                            if (cell.entityidentifier == entity.getIdentifier()) {
     461                                record.removeFromImportcells(cell)
     462                            }
    196463                        }
    197                      }
     464                    }
    198465                } // end of fielderrors
    199             } // end of record
    200         } // end of table
    201 
    202         // a new ontology term was added, so stay at the current step otherwise go to the next step
    203         if (params.updatefield) render(view:"step3_simple", model:[datamatrix:session.importer_importeddata, failedcells:session.importer_failedcells])
    204             else
    205         if (invalidentities)
    206             render(view:"step3_simple", model:[datamatrix:session.importer_importeddata, failedcells:session.importer_failedcells, invalidentities:invalidentities])
    207         else
    208             render(view:"step3", model:[datamatrix:session.importer_importeddata])
    209     }
    210 
    211     /*
    212      * Store the corrected cells back into the datamatrix. Be sure to check
    213      * if the corrected ontology is not blank. If so, it should keep
    214      * the original value which was read from the Excel file.
     466            } // end of record
     467        } // end of table
     468
     469        return (flow.importer_invalidentities == 0) ? true : false
     470    } // end of method
     471
     472    /**
     473     * Handle the imported entities page.
    215474     *
    216      * @param cell array of cells with corrected cells (ontologies)
    217      *
    218     */
    219     def saveCorrectedCells = {
    220         def correctedcells = [:]
    221 
    222         // Loop through the form with cell fields and values
    223         params.cell.index.each { cellhash, value ->
    224             correctedcells.put(cellhash, value)
    225         }
    226 
    227         // Store the corrected cells back into the datamatrix
    228         ImporterService.saveCorrectedCells(
    229                     session.importer_importeddata,
    230                     session.importer_failedcells,
    231                     correctedcells)
    232 
    233         render(view:"step3_simple", model:[datamatrix:session.importer_importeddata])
    234 
    235     }
    236 
    237     /**
    238     * User has assigned all entities and templatefieldtypes to the columns and continues to the next step (assigning properties to columns)
    239     * All information of the columns is stored in a session as MappingColumn object
    240     *
    241     * @param entities list of entities and columns it has been assigned to (columnindex.entitytype)
    242     * @param templatefieldtype list of celltypes and columns it has been assigned to (columnindex:templatefieldtype format)
    243     * @return properties page
    244     *
    245     * @see celltype: http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html
    246     */
    247     def savePreview = {
    248         def tft = null 
    249         def identifiercolumnindex = (params.identifier!=null) ? params.identifier.toInteger() : -1
    250         def selectedentities = []
    251 
    252         // loop all entities and see which column has been assigned which entitytype
    253         // and build an array containing the selected entities
    254         params.entity.index.each { columnindex, entityname ->
    255             def _entity = [name:entityname,columnindex:columnindex.toInteger()]
    256             selectedentities.add(_entity)
    257         }
    258 
    259         params.templatefieldtype.index.each { columnindex, _templatefieldtype ->
    260             switch (_templatefieldtype) {
    261                 case "STRING"       : tft = TemplateFieldType.STRING
    262                                       break
    263                 case "TEXT"         : tft = TemplateFieldType.TEXT
    264                                       break
    265                 case "LONG"         : tft = TemplateFieldType.LONG
    266                                       break
    267                 case "DOUBLE"       : tft = TemplateFieldType.DOUBLE
    268                                       break
    269                 case "STRINGLIST"   : tft = TemplateFieldType.STRINGLIST
    270                                       break
    271                 case "ONTOLOGYTERM" : tft = TemplateFieldType.ONTOLOGYTERM
    272                                       break
    273                 case "DATE"         : tft = TemplateFieldType.DATE
    274                                       break
    275                 default: break
    276             }
    277            
    278             // Set the templatefield type for this column
    279             session.importer_header[columnindex.toInteger()].templatefieldtype = tft
    280         }
    281 
    282         // Detect the entity type
    283         params.entity.index.each { columnindex, entityname ->
    284             Class clazz = null
    285 
    286             switch (entityname) {
    287                 case "Study"    : clazz = dbnp.studycapturing.Study
    288                         break
    289                 case "Subject"  : clazz = dbnp.studycapturing.Subject
    290                         break
    291                 case "Event"    : clazz = dbnp.studycapturing.Event
    292                         break
    293                 case "Protocol" : clazz = dbnp.studycapturing.Protocol
    294                         break
    295                 case "Sample"   : clazz = dbnp.studycapturing.Sample
    296                         break
    297                 default: clazz = Object
    298                         break
    299             }
    300 
    301             // Store properties for this column
    302             session.importer_header[columnindex.toInteger()].identifier = (columnindex.toInteger() == identifiercolumnindex) ? true : false
    303             session.importer_header[columnindex.toInteger()].index = columnindex.toInteger()
    304             session.importer_header[columnindex.toInteger()].entity = clazz
    305         }
    306 
    307         // currently only one template is used for all entities
    308         // TODO: show template fields per entity
    309        
    310         def templates = Template.get(session.importer_template_id)
    311 
    312         render(view:"step2", model:[entities:selectedentities, header:session.importer_header, templates:templates])
    313     }
    314    
    315     /**
    316      * Method which stores the properties set per column and then imports the data.
    317      *
    318      * @param columnproperty array of columns containing index and property (represented as a String)
    319     *
    320     */
    321     def saveProperties = {       
    322 
    323         // Find actual Template object from the chosen template name
    324         def template = Template.get(session.importer_template_id)
    325 
    326         params.columnproperty.index.each { columnindex, property ->
    327 
    328                 // Create an actual class instance of the selected entity with the selected template
    329                 // This should be inside the closure because in some cases in the advanced importer, the fields can have different target entities
    330                 def entityClass = Class.forName(session.importer_header[columnindex.toInteger()].entity.getName(), true, this.getClass().getClassLoader())
    331                 def entityObj = entityClass.newInstance(template:template)
    332 
    333                 // Store the selected property for this column into the column map for the ImporterService
    334                 session.importer_header[columnindex.toInteger()].property = property
    335 
    336                 // Look up the template field type of the target TemplateField and store it also in the map
    337                 session.importer_header[columnindex.toInteger()].templatefieldtype = entityObj.giveFieldType(property)
    338 
    339                 // Is a "Don't import" property assigned to the column?
    340                 session.importer_header[columnindex.toInteger()].dontimport = (property=="dontimport") ? true : false
    341 
    342                 //if it's an identifier set the mapping column true or false
    343                 entityObj.giveFields().each {
    344                     (it.preferredIdentifier && (it.name==property)) ? session.importer_header[columnindex.toInteger()].identifier = true : false
    345                 }
    346         }
    347 
    348         // Import the workbook and store the table with entity records and store the failed cells
    349         def (table, failedcells) = ImporterService.importData(session.importer_template_id, session.importer_workbook, session.importer_sheetindex, session.importer_datamatrix_start, session.importer_header)
    350 
    351         session.importer_importeddata = table       
    352         session.importer_failedcells = failedcells
    353 
    354         // Are there any failed cells, then show an extra step to correct the cells
    355         /*if (failedcells.size()!=0)
    356             render(view:"step2a_simple", model:[failedcells:session.importer_failedcells])
    357         else {*/
    358             if (params.layout=="horizontal")
    359                 render(view:"step3_simple", model:[datamatrix:session.importer_importeddata, failedcells:session.importer_failedcells])
    360             else if (params.layout=="vertical")
    361                 render(view:"step3", model:[datamatrix:session.importer_importeddata])
    362         //}
    363     }
    364 
    365     /**
    366      * Method which saves the data matrix to the database
    367      */
    368     def savePostview = {       
    369 
    370         // Called this page directly, then display an error message.
    371         if ( (!session?.import_wizard_init) ) {
    372             render (template:"common/error",
    373                     model:[error:"Data is already imported or you are calling the url directly without following the previous import steps."])
    374         } else {
    375             def (validatedSuccesfully, updatedEntities, failedtopersist) = ImporterService.saveDatamatrix(session.importer_study, session.importer_importeddata)
    376             session.validatedSuccesfully = validatedSuccesfully
    377             render(view:"step4", model:[validatedSuccesfully:session.validatedSuccesfully, failedtopersist:failedtopersist, updatedentities:updatedEntities, totalrows:session.importer_importeddata.size, referer: session.import_referer])
    378             session.import_wizard_init = false
    379         }
    380     }
    381 
    382     /**
    383     * Return templates which belong to a certain entity type
    384     *
    385     * @param entity entity name string (Sample, Subject, Study et cetera)
    386     * @return JSON object containing the found templates
    387     */
    388     def ajaxGetTemplatesByEntity = {       
    389         def entityName = Blowfish.decryptBase64(
    390                         params.entity,
    391                         grailsApplication.config.crypto.shared.secret
    392                     )
    393 
    394         //def entityClass = grailsApplication.config.gscf.domain.importableEntities.get(params.entity).entity
    395         def entityClass = entityName
    396 
    397         // fetch all templates for a specific entity
    398         def templates = Template.findAllByEntity(Class.forName(entityClass, true, this.getClass().getClassLoader()))   
    399 
    400         // render as JSON
    401         render templates as JSON
    402     }
    403 
    404     def refresh = {
    405        // params
     475     * @param Map LocalAttributeMap (the flow scope)
     476     * @param Map GrailsParameterMap (the flow parameters = form data)
     477     * @returns boolean true if correctly validated, otherwise false
     478     */
     479    boolean importedPage(flow, params) {
     480        return true
     481    }
     482
     483    boolean saveEntities(flow, params) {
     484            def (validatedSuccesfully, updatedEntities, failedToPersist) = ImporterService.saveDatamatrix(flow.importer_study, flow.importer_importeddata)
     485
     486            flow.importer_validatedsuccesfully = validatedSuccesfully
     487            flow.importer_failedtopersist = failedToPersist
     488            flow.imported_updatedentities = updatedEntities
     489            flow.importer_totalrows = flow.importer_importeddata.size
     490            flow.importer_referer = ""
     491
     492            return true
    406493    }
    407494}
  • trunk/grails-app/domain/dbnp/importer/ImportCell.groovy

    r1202 r1277  
    1818 */
    1919
    20 class ImportCell extends Identity {
     20class ImportCell extends Identity implements Serializable {
    2121    MappingColumn mappingcolumn
    2222    int entityidentifier
  • trunk/grails-app/domain/dbnp/importer/ImportMapping.groovy

    r959 r1277  
    11package dbnp.importer
    22
    3 class ImportMapping {
     3class ImportMapping implements Serializable {
    44
    55        static hasMany = [columns: MappingColumn]
  • trunk/grails-app/domain/dbnp/importer/ImportRecord.groovy

    r1121 r1277  
    1616import dbnp.studycapturing.Identity
    1717
    18 class ImportRecord extends Identity {
     18class ImportRecord extends Identity implements Serializable {
    1919    static hasMany = [ importcells: ImportCell ]
    2020   
  • trunk/grails-app/domain/dbnp/importer/MappingColumn.groovy

    r1121 r1277  
    1212* identifier: true if this column is identifying (unique/primary key)
    1313*/
    14 class MappingColumn {
     14class MappingColumn implements Serializable {
    1515
    1616        String name
  • trunk/grails-app/services/dbnp/importer/ImporterService.groovy

    r1223 r1277  
    1717package dbnp.importer
    1818import org.apache.poi.ss.usermodel.*
     19import org.apache.poi.hssf.usermodel.HSSFCell
    1920
    2021import dbnp.studycapturing.TemplateFieldType
     
    5051        //def header = []
    5152        def header = [:]
    52         def df = new DataFormatter()
     53    def df = new DataFormatter()
    5354        def property = new String()
    5455
     
    6162            def datamatrix_celldata = df.formatCellValue(sheet.getRow(datamatrix_start).getCell(columnindex))
    6263            def datamatrix_cell     = sheet.getRow(datamatrix_start).getCell(columnindex)           
    63             def headercell = sheet.getRow(headerrow-1+sheet.getFirstRowNum()).getCell(columnindex)
     64        def headercell = sheet.getRow(headerrow-1+sheet.getFirstRowNum()).getCell(columnindex)
    6465            def tft = TemplateFieldType.STRING //default templatefield type
    6566
    66             // Check for every celltype, currently redundant code, but possibly this will be
     67        // Check for every celltype, currently redundant code, but possibly this will be
    6768            // a piece of custom code for every cell type like specific formatting         
    6869               
    6970            switch (datamatrix_celltype) {
    70                     case Cell.CELL_TYPE_STRING:
    71                             //parse cell value as double
    72                             def doubleBoolean = true
    73                             def fieldtype = TemplateFieldType.STRING
    74 
    75                             // is this string perhaps a double?
    76                             try {
    77                                 formatValue(datamatrix_celldata, TemplateFieldType.DOUBLE)
    78                             } catch (NumberFormatException nfe) { doubleBoolean = false }
    79                             finally {
    80                                 if (doubleBoolean) fieldtype = TemplateFieldType.DOUBLE
    81                             }
    82 
    83                             header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
     71                case Cell.CELL_TYPE_STRING:
     72                    //parse cell value as double
     73                    def doubleBoolean = true
     74                    def fieldtype = TemplateFieldType.STRING
     75
     76                    // is this string perhaps a double?
     77                    try {
     78                        formatValue(datamatrix_celldata, TemplateFieldType.DOUBLE)
     79                    } catch (NumberFormatException nfe) { doubleBoolean = false }
     80                    finally {
     81                        if (doubleBoolean) fieldtype = TemplateFieldType.DOUBLE
     82                    }
     83
     84                    header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
    8485                                                                            templatefieldtype:fieldtype,
    8586                                                                            index:columnindex,
     
    8788                                                                            property:property);
    8889
    89                             break
    90                     case Cell.CELL_TYPE_NUMERIC:
    91                             def fieldtype = TemplateFieldType.LONG
    92                             def doubleBoolean = true
    93                             def longBoolean = true
    94 
    95                             // is this cell really an integer?
    96                             try {
    97                                 Long.valueOf(datamatrix_celldata)
    98                             } catch (NumberFormatException nfe) { longBoolean = false }
    99                             finally {
    100                                 if (longBoolean) fieldtype = TemplateFieldType.LONG
    101                             }
    102 
    103                             // it's not an long, perhaps a double?
    104                             if (!longBoolean)
    105                                 try {
    106                                     formatValue(datamatrix_celldata, TemplateFieldType.DOUBLE)
    107                                 } catch (NumberFormatException nfe) { doubleBoolean = false }
    108                                 finally {
    109                                     if (doubleBoolean) fieldtype = TemplateFieldType.DOUBLE
    110                                 }
    111 
    112                             if (DateUtil.isCellDateFormatted(datamatrix_cell)) fieldtype = TemplateFieldType.DATE
    113 
    114                             header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
     90                    break
     91                case Cell.CELL_TYPE_NUMERIC:
     92                    def fieldtype = TemplateFieldType.LONG
     93                    def doubleBoolean = true
     94                    def longBoolean = true
     95
     96                    // is this cell really an integer?
     97                    try {
     98                        Long.valueOf(datamatrix_celldata)
     99                    } catch (NumberFormatException nfe) { longBoolean = false }
     100                    finally {
     101                        if (longBoolean) fieldtype = TemplateFieldType.LONG
     102                    }
     103
     104                    // it's not an long, perhaps a double?
     105                    if (!longBoolean)
     106                    try {
     107                                    formatValue(datamatrix_celldata, TemplateFieldType.DOUBLE)
     108                                } catch (NumberFormatException nfe) { doubleBoolean = false }
     109                                finally {
     110                                    if (doubleBoolean) fieldtype = TemplateFieldType.DOUBLE
     111                                }
     112
     113                    if (DateUtil.isCellDateFormatted(datamatrix_cell)) fieldtype = TemplateFieldType.DATE
     114
     115                    header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
    115116                                                                            templatefieldtype:fieldtype,
    116117                                                                            index:columnindex,
    117118                                                                            entity:theEntity,
    118119                                                                            property:property);
    119                             break
    120                     case Cell.CELL_TYPE_BLANK:
    121                             header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
     120                    break
     121                case Cell.CELL_TYPE_BLANK:
     122                    header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
    122123                                                                            templatefieldtype:TemplateFieldType.STRING,
    123124                                                                            index:columnindex,
    124125                                                                            entity:theEntity,
    125126                                                                            property:property);
    126                             break
    127                     default:
    128                             header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
     127                    break
     128                default:
     129                    header[columnindex] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell),
    129130                                                                            templatefieldtype:TemplateFieldType.STRING,
    130131                                                                            index:columnindex,
    131132                                                                            entity:theEntity,
    132133                                                                            property:property);
    133                             break
    134             } // end of switch
    135         } // end of cell loop
     134                    break
     135                } // end of switch
     136        } // end of cell loop
    136137        return header
    137138    }
     
    147148     */
    148149
    149     Cell[][] getDatamatrix(Workbook wb, header, int sheetindex, int datamatrix_start, int count) {
     150    HSSFCell[][] getDatamatrix(Workbook wb, header, int sheetindex, int datamatrix_start, int count) {
    150151        def sheet = wb.getSheetAt(sheetindex)
    151152        def rows  = []
     
    165166           
    166167            (0..header.size()-1).each { columnindex ->
    167                 def c = sheet.getRow(rowindex).getCell(columnindex, Row.CREATE_NULL_AS_BLANK)
    168                 //row.add(df.formatCellValue(c))
    169                 row.add(c)
     168            def c = sheet.getRow(rowindex).getCell(columnindex, Row.CREATE_NULL_AS_BLANK)           
     169            row.add(c)
    170170            }
    171171            rows.add(row)
     
    281281    def saveDatamatrix(Study study, datamatrix) {
    282282        def validatedSuccesfully = 0
    283         def entitystored = null
    284         def failedtopersist = []
    285         def persisterrors = []
    286         def updatedentities = []
    287         study.refresh()
     283    def entitystored = null
     284    def failedtopersist = []
     285    def persisterrors = []
     286    def updatedentities = []
     287    study.refresh()
    288288       
    289289        // go through the data matrix, read every record and validate the entity and try to persist it
    290290        datamatrix.each { record ->
    291             record.each { entity ->
     291            record.each { entity ->           
    292292                        switch (entity.getClass()) {
    293                         case Study       :  print "Persisting Study `" + entity + "`: "
    294                                                 entity.owner = AuthenticationService.getLoggedInUser()
    295                                                 println "storing study" + entity
    296                                                 println "dump=" + entity.dump()
    297                                                 println "validate=" + entity.validate()
     293                        case Study       :  log.info "Persisting Study `" + entity + "`: "
     294                                                entity.owner = AuthenticationService.getLoggedInUser()                                             
    298295                                                if (persistEntity(entity)) validatedSuccesfully++;
    299296                                                    else failedtopersist.add(entity)
    300                                                 break
    301                         case Subject     :  print "Persisting Subject `" + entity + "`: "
    302                                                 entity.parent = study
     297                                        break
     298                        case Subject :  log.info "Persisting Subject `" + entity + "`: "
     299                                        entity.parent = study
     300
     301                                        // is the current entity not already in the database?
     302                                        entitystored = isEntityStored(entity)
    303303                                               
    304                                                 // is the current entity not already in the database?
    305                                                 entitystored = isEntityStored(entity)
     304                                        // this entity is new, so add it to the study
     305                                        if (entitystored==null) study.addToSubjects(entity)
     306                                            else { // existing entity, so update it
     307                                                updateEntity(entitystored, entity)
     308                                                updatedentities.add(entity)
     309                                            }
     310
     311                                        if (persistEntity(study)) validatedSuccesfully++;
     312                                            else failedtopersist.add(entity)
     313                                        break
     314                        case Event       :  log.info "Persisting Event `" + entity + "`: "
     315                                        entity.parent = study
     316                                        study.addToEvents(entity)
     317                                        if (persistEntity(entity)) validatedSuccesfully++;
     318                                            else failedtopersist.add(entity)
     319                                        break
     320                        case Sample      :  log.info "Persisting Sample `" + entity +"`: "
     321                                        entity.parent = study
    306322                                               
    307                                                 // this entity is new, so add it to the study
    308                                                 if (entitystored==null) study.addToSubjects(entity)
    309                                                 else { // existing entity, so update it
    310                                                     updateEntity(entitystored, entity)
    311                                                     updatedentities.add(entity)
    312                                                 }
    313 
     323                                        // is this sample validatable (sample name unique for example?)
     324                                        if (entity.validate()) {
     325                                            study.addToSamples(entity)
    314326                                                if (persistEntity(study)) validatedSuccesfully++;
    315                                                     else failedtopersist.add(entity)
    316                                                 break
    317                         case Event       :  print "Persisting Event `" + entity + "`: "
    318                                                 entity.parent = study
    319                                                 study.addToEvents(entity)
    320                                                 if (persistEntity(entity)) validatedSuccesfully++;
    321                                                     else failedtopersist.add(entity)
    322                                                 break
    323                         case Sample      :  print "Persisting Sample `" + entity +"`: "                                               
    324                                                 entity.parent = study
    325                                                
    326                                                 // is this sample validatable (sample name unique for example?)
    327                                                 if (entity.validate()) {
    328                                                     study.addToSamples(entity)
    329                                                     if (persistEntity(study)) validatedSuccesfully++;                                                       
    330                                                 } else {
    331                                                     failedtopersist.add(entity)
    332                                                 }
    333                                                
    334                                                 break
    335                         case SamplingEvent: print "Persisting SamplingEvent `" + entity + "`: "
    336                                                 entity.parent = study
    337                                                 study.addToSamplingEvents(entity)
    338                                                 if (persistEntity(entity)) validatedSuccesfully++;
    339                                                     else failedtopersist.add(entity)
    340                                                 break
    341                         default          :  println "Skipping persisting of `" + entity.getclass() +"`"
    342                                                 failedtopersist.add(entity)
    343                                                 break
     327                                        } else {
     328                                            failedtopersist.add(entity)
     329                                        }
     330                                        break
     331                    case SamplingEvent: log.info "Persisting SamplingEvent `" + entity + "`: "
     332                                        entity.parent = study
     333                                        study.addToSamplingEvents(entity)
     334                                        if (persistEntity(entity)) validatedSuccesfully++;
     335                                            else failedtopersist.add(entity)
     336                                        break
     337                        default          :  log.info "Skipping persisting of `" + entity.getclass() +"`"
     338                                        failedtopersist.add(entity)
     339                                        break
    344340                        } // end switch
    345341            } // end record
    346         } // end datamatrix
     342        } // end datamatrix   
    347343        return [validatedSuccesfully, updatedentities, failedtopersist]
    348344    }
     
    360356                        case Study          :  return Study.findByCode(entity.code)
    361357                                               break
    362                         case Subject        :  return Subject.findByParentAndName(entity.parent, entity.name)
     358                        case Subject        :  return Subject.findByParentAndName(entity.parent, entity.name)
    363359                                               break
    364360                        case Event          :  break
     
    383379        switch (entity.getClass()) {
    384380                        case Study          :  break
    385                         case Subject        :  entitystored.properties = entity.properties
     381                        case Subject        :  entitystored.properties = entity.properties
    386382                                               entitystored.save()
    387383                                               break
     
    434430                def df = new DataFormatter()
    435431                def template = Template.get(template_id)
    436                 def tft = TemplateFieldType
     432        def tft = TemplateFieldType
    437433                def record = [] // list of entities and the read values
    438                 def failed = new ImportRecord() // map with entity identifier and failed mappingcolumn
     434        def failed = new ImportRecord() // map with entity identifier and failed mappingcolumn
    439435
    440436                // Initialize all possible entities with the chosen template
     
    459455                                }
    460456
    461                                 try {
    462                                 // which entity does the current cell (field) belong to?
    463                                     switch (mc.entity) {
    464                                         case Study: // does the entity already exist in the record? If not make it so.
    465                                                 (record.any {it.getClass() == mc.entity}) ? 0 : record.add(study)
     457                try {
     458                    // which entity does the current cell (field) belong to?
     459                    switch (mc.entity) {
     460                        case Study: // does the entity already exist in the record? If not make it so.
     461                        (record.any {it.getClass() == mc.entity}) ? 0 : record.add(study)
    466462                                                study.setFieldValue(mc.property, value)
    467463                                                break
    468                                         case Subject: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(subject)
     464                        case Subject: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(subject)
    469465                                                subject.setFieldValue(mc.property, value)
    470466                                                break
    471                                         case SamplingEvent: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(samplingEvent)
     467                        case SamplingEvent: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(samplingEvent)
    472468                                                samplingEvent.setFieldValue(mc.property, value)
    473469                                                break
    474                                         case Event: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(event)
     470                        case Event: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(event)
    475471                                                event.setFieldValue(mc.property, value)
    476472                                                break
    477                                         case Sample: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(sample)
     473                        case Sample: (record.any {it.getClass() == mc.entity}) ? 0 : record.add(sample)
    478474                                                sample.setFieldValue(mc.property, value)
    479475                                                break
    480                                         case Object:   // don't import
     476                        case Object:   // don't import
    481477                                                break
    482                                     } // end switch
    483                                 } catch (IllegalArgumentException iae) {
    484                                     // store the mapping column and value which failed
    485                                     def identifier
    486 
    487                                     switch (mc.entity) {
    488                                         case Study:  identifier = study.getIdentifier()
    489                                                 break
    490                                         case Subject: identifier = subject.getIdentifier()
    491                                                 break
    492                                         case SamplingEvent: identifier = samplingEvent.getIdentifier()
    493                                                 break
    494                                         case Event: identifier = event.getIdentifier()                                         
    495                                                 break
    496                                         case Sample: identifier = sample.getIdentifier()
    497                                                 break
    498                                         case Object:   // don't import
    499                                                 break
    500                                     }
     478                    } // end switch
     479                } catch (IllegalArgumentException iae) {
     480                    // store the mapping column and value which failed
     481                    def identifier
     482
     483                    switch (mc.entity) {
     484                        case Study:  identifier = study.getIdentifier()
     485                        break
     486                        case Subject: identifier = subject.getIdentifier()
     487                        break
     488                        case SamplingEvent: identifier = samplingEvent.getIdentifier()
     489                        break
     490                        case Event: identifier = event.getIdentifier()
     491                        break
     492                        case Sample: identifier = sample.getIdentifier()
     493                        break
     494                        case Object:   // don't import
     495                        break
     496                    }
    501497                                   
    502                                     def mcInstance = new MappingColumn()
    503                                     mcInstance.properties = mc.properties
    504                                     failed.addToImportcells(new ImportCell(mappingcolumn:mcInstance, value:value, entityidentifier:identifier))
    505                                 }
     498                    def mcInstance = new MappingColumn()
     499                    mcInstance.properties = mc.properties
     500                    failed.addToImportcells(new ImportCell(mappingcolumn:mcInstance, value:value, entityidentifier:identifier))
     501                }
    506502                        } // end
    507503                } // end for
     
    515511    * @return object corresponding to the TemplateFieldType
    516512    */
    517     def formatValue(String value, TemplateFieldType type) throws NumberFormatException {
     513   def formatValue(String value, TemplateFieldType type) throws NumberFormatException {
    518514            switch (type) {
    519                 case TemplateFieldType.STRING       :   return value.trim()
    520                 case TemplateFieldType.TEXT         :   return value.trim()
    521                 case TemplateFieldType.LONG         :   return (long) Double.valueOf(value)
    522                 //case TemplateFieldType.FLOAT      :   return Float.valueOf(value.replace(",","."));
    523                 case TemplateFieldType.DOUBLE       :   return Double.valueOf(value.replace(",","."));
    524                 case TemplateFieldType.STRINGLIST   :   return value.trim()
    525                 case TemplateFieldType.ONTOLOGYTERM :   return value.trim()
    526                 case TemplateFieldType.DATE         :   return value
    527                 default                             :   return value
     515            case TemplateFieldType.STRING           :   return value.trim()
     516            case TemplateFieldType.TEXT         :   return value.trim()
     517            case TemplateFieldType.LONG         :   return (long) Double.valueOf(value)
     518            //case TemplateFieldType.FLOAT          :   return Float.valueOf(value.replace(",","."));
     519            case TemplateFieldType.DOUBLE           :   return Double.valueOf(value.replace(",","."));
     520            case TemplateFieldType.STRINGLIST   :   return value.trim()
     521            case TemplateFieldType.ONTOLOGYTERM :   return value.trim()
     522            case TemplateFieldType.DATE         :   return value
     523            default                             :   return value
    528524            }
    529525    }
  • trunk/grails-app/taglib/dbnp/importer/ImporterTagLib.groovy

    r1202 r1277  
    6969     */
    7070    def failedCells = { attrs ->
    71         def failedcells = attrs['failedcells']
    72         out << render (template:"common/failedcells", model:[failedcells:failedcells])
     71        def failedcells = attrs['failedcells']
     72        out << render (template:"common/failedcells", model:[failedcells:failedcells])
    7373    }
    7474
     
    7676     * @param entities array containing selected entities
    7777     * @param header array containing mappingcolumn objects
    78      * @param allfieldtypes if set, show all fields
    79      * @param layout constant value: "horizontal" or "vertical"
     78     * @param allfieldtypes if set, show all fields   
    8079     */
    8180    def properties = { attrs ->
    8281        def header = attrs['header']
    8382        def entities = attrs['entities']
    84         def allfieldtypes = (attrs['allfieldtypes']==null) ? "false" : "true"
    85         def layout = (attrs['layout']==null) ? "vertical" : attrs['layout']
    86 
    87         //choose template for vertical layout (default) or horizontal layout
    88         def template = (layout == "vertical") ? "common/properties_vertical" : "common/properties_horizontal"
    89        
    90         out << render ( template:template,
    91                         model:[selectedentities:entities,
    92                         standardentities:grailsApplication.config.gscf.domain.importableEntities,
    93                         header:header,
    94                         allfieldtypes:allfieldtypes,
    95                         layout:layout]
    96                         )
     83
     84        out << render ( template:"common/properties_horizontal" )
    9785    }
    9886
     
    11098        // TODO: this should be changed to retrieving fields per entity instead of from one template
    11199        //       and session variables should not be used inside the service, migrate to controller
    112 
    113         def t = Template.get(session.importer_template_id)
     100   
     101        def t = Template.get(attrs['template_id'])
    114102        def mc = attrs['mappingcolumn']
    115103        def allfieldtypes = attrs['allfieldtypes']
    116         def matchvalue = attrs['matchvalue']
     104    def matchvalue = attrs['matchvalue']
    117105        def domainfields = mc.entity.giveDomainFields().findAll { it.type == mc.templatefieldtype }
    118106            domainfields = domainfields.findAll { it.preferredIdentifier != mc.identifier}
  • trunk/grails-app/views/importer/common/_missingproperties.gsp

    r1216 r1277  
    3737        style   : 'addMore',
    3838        onClose : function(scope) {
    39             //refreshWebFlow();?
     39            refreshFlow();           
    4040             //location.reload();
    41              updatefield = '<input type = "hidden" name="updatefield" value="true" / >';
     41             /*updatefield = '<input type = "hidden" name="updatefield" value="true" / >';
    4242             $('#missingpropertiesform').append(updatefield);
    43              $('#missingpropertiesform').submit();
     43             $('#missingpropertiesform').submit();*/
    4444        }
    4545    });
    46 
    4746
    4847  });
     
    6362  });
    6463</script>
    65 
    66 <g:if test="${invalidentities}">
    67   <p><b>There are ${invalidentities} entities which could not be validated, they are indicated by a red color, please correct them before continuing.</b></p>
     64 
     65<g:if test="${importer_invalidentities}"><br/><br/>
     66  <b>There are ${importer_invalidentities} entities which could not be validated, they are indicated by a red color, please correct them before continuing.</b>
    6867</g:if>
    6968
    7069<div class="wizard" id="wizard">
    71 <g:form name="missingpropertiesform" id="missingpropertiesform" action="saveMissingProperties">
    7270    <div class="table">
    7371        <g:set var="showHeader" value="${true}"/>
     
    9290    </div>
    9391    <div>
    94         <br/>
    95         <input type="submit" value="Accept changes">
     92        <br/>   
    9693    </div>
    97 </g:form>   
    9894</div>
  • trunk/grails-app/views/importer/common/_postview.gsp

    r959 r1277  
    1313         */
    1414%>
    15 <g:form name="postviewform" action="savePostview">
    1615    <table>     
    1716        <tr>     
     
    3736            </g:each>
    3837        </tr>
    39     </table>
    40     <table>
    41         <tr>
    42             <td colspan="">
    43                 <input type="submit" value="This is OK, store the imported data">
    44             </td>
    45         </tr>
    46     </table>
    47 </g:form>
     38    </table>
  • trunk/grails-app/views/importer/common/_properties_horizontal.gsp

    r1231 r1277  
    2929});
    3030</script>
    31 <g:form name="propertiesform" action="saveProperties">
     31<!-- saveproperties action was defined in the form -->
    3232    <table>
    33           <g:each var="stdentity" in ="${standardentities}">           
    34               <% if (selectedentities.any { it.name.toLowerCase() == stdentity.value.entity.toLowerCase() } && stdentity.value.entity!="") { %>
     33          <g:each var="stdentity" in ="${importer_importableentities}">
     34              <% if (importer_selectedentities.any { it.name.toLowerCase() == stdentity.value.entity.toLowerCase() } && stdentity.value.entity!="") { %>
     35           
    3536              <tr><td colspan="3"><h4>${stdentity.value.name}</h4></td></tr>
    3637                <tr>
    37                   <td class="header" width="25px"><input id="clearselect" type="button" value="clear" name="clearselect"></td>
    38                 <g:each var="selentity" in="${selectedentities}">                   
    39                     <g:if test="${selentity.name.toLowerCase()==stdentity.value.entity.toLowerCase()}">
     38            <td class="header" width="25px"><input id="clearselect" type="button" value="clear" name="clearselect"></td>
     39            <g:each var="selentity" in="${importer_selectedentities}">
     40              <g:if test="${selentity.name.toLowerCase()==stdentity.value.entity.toLowerCase()}">
    4041                            <td class="header" width="200px">
    41                                 <b>${header[selentity.columnindex.toInteger()].name}</b>
    42                                 <importer:propertyChooser name="columnproperty" mappingcolumn="${header[selentity.columnindex.toInteger()]}" matchvalue="${header[selentity.columnindex.toInteger()].name}" allfieldtypes="${allfieldtypes}"/>
     42                                <b>${importer_header[selentity.columnindex.toInteger()].name}</b>
     43                  <importer:propertyChooser name="columnproperty" mappingcolumn="${importer_header[selentity.columnindex.toInteger()]}" matchvalue="${importer_header[selentity.columnindex.toInteger()].name}" template_id="${importer_template_id}" allfieldtypes="${importer_allfieldtypes}"/>
    4344                            </td>                                       
    44                     </g:if>
    45                 </g:each>
     45              </g:if>
     46            </g:each>
    4647                </tr>
    47                 <g:each var="row" in="${datamatrix}">
     48
     49        <g:each var="row" in="${session.importer_datamatrix}">
    4850                <tr>
    49                   <td class="datamatrix">
     51                  <td class="datamatrix">                   
    5052                  </td>
    5153                    <g:each var="cell" in="${row}">
     
    5759                </tr>
    5860                </g:each>
    59                 <tr>
    60                   <td colspan="${header.size()}">
    61                       <hr />
    62                   </td>
    63                 </tr>
     61
    6462          <% } %> <!-- end of JSP if-->
    65           </g:each>     
    66         <tr>
    67             <td>
    68                 <input type="hidden" name="layout" value="${layout}">
    69                 <input type="submit" name="savebutton" value="Next"/>
    70             </td>
    71         </tr>
    72     </table>   
    73 </g:form>
     63          </g:each>             
     64    </table>
  • trunk/web-app/css/importer.css

    r959 r1277  
     1/**
     2 * ajaxflow css
     3 *
     4 * @author      Jeroen Wesbeek
     5 * @since       20101214
     6 *
     7 * Revision information:
     8 * $Rev$
     9 * $Author$
     10 * $Date$
     11 */
     12
     13/** START :: AJAX FLOW **/
     14.ajaxFlow {
     15        width: 100%;
     16}
     17.ajaxFlow h1 {
     18        color: #006DBA;
     19        font-weight: bold;
     20        font-size: 18px;
     21        padding-bottom: 10px;
     22}
     23.ajaxFlowError {
     24        width: 97.5%;
     25        border: 1px dotted red;
     26        padding: 10px 10px 10px 10px;
     27}
     28
     29/** START :: TABS **/
     30.tabs {
     31    display: block;
     32    padding-bottom: 2px;
     33    border-bottom: 2px solid #006DBA;
     34    width: 100%;
     35}
     36.tabs ul {
     37    list-style-type: none; /* suppression of useless elements */
     38    padding: 0px;
     39    font-size: 10px;
     40    margin: 0px;
     41    font-family: Verdana, Arial, Helvetica, sans-serif;
     42    font-size: 10px;
     43    height: 20px;
     44    width: 100%;
     45}
     46.tabs li {
     47    float: left;
     48    margin: 0px;
     49    height: 20px;
     50    float: left;
     51    display: block;
     52    text-align: center;
     53    text-decoration: none;
     54    color: #006DBA;
     55    background: #CCC;
     56    font-weight: bold;
     57}
     58.tabs li input {
     59        cursor: pointer;
     60        color: #006DBA;
     61        background-color: transparent;
     62        border: none;   
     63}
     64.tabs li:last-child:after {
     65        content: url('../images/importer/spacer.gif');
     66}
     67.tabs li:first-child:before {
     68        content: url('../images/importer/spacer.gif');
     69}
     70.tabs li:before {
     71        content:url(../images/importer/arrowR.gif);
     72        position:inherit;
     73        margin-top: 0px;
     74        margin-bottom: 0px;
     75        display:inline;
     76}
     77.tabs li:after {
     78        content:url(../images/importer/arrowL.gif);
     79        position:inherit;
     80        margin-top: 0px;
     81        margin-bottom: 0px;
     82        display:inline;
     83}
     84.tabs .content {
     85    padding: 0px 10px 0px 10px;
     86    display: inline;
     87    border: 0px;
     88        vertical-align: top;
     89        line-height: 20px;
     90}
     91.tabs .active {
     92    background-color: #006DBA !important;
     93    color: #fff !important;
     94    text-shadow: 0px 0px 1px #333;
     95}
     96
     97/** START NAVIGATION **/
     98.navigation {
     99    display: block;
     100    padding-top: 2px;
     101    border-top: 2px solid #006DBA;
     102    width: 100%;
     103        color: #666666;
     104        font-size: 10px;
     105}
     106
     107.navigation .prevnext {
     108    cursor: pointer;
     109    color: #006DBA;
     110    background-color: transparent;
     111    border: none;
     112}
     113
     114/** CONTENT STYLES **/
     115.content {
     116        padding: 20px 0px 20px 0px;
     117}
     118
     119.content h1 {
     120        color: #006DBA;
     121        font-weight: bold;
     122        font-size: 18px;
     123}
     124.content p {
     125        text-align: justify;
     126        padding: 10px 0px 10px 0px;
     127}
     128
     129.content a, .content a:visited {
     130        color: red;
     131        text-decoration: none;
     132}
     133
    1134.header
    2135{
     
    37170}
    38171
    39 .validationfail {       
     172.validationfail {
    40173    color: red;
    41174}
Note: See TracChangeset for help on using the changeset viewer.