Ignore:
Timestamp:
Dec 16, 2010, 3:42:15 PM (10 years ago)
Author:
t.w.abma@…
Message:
  • rewrite of the Importer Wizard into an Ajaxflow
File:
1 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}
Note: See TracChangeset for help on using the changeset viewer.