Changeset 1277

Show
Ignore:
Timestamp:
16-12-10 15:42:15 (3 years ago)
Author:
t.w.abma@…
Message:

- rewrite of the Importer Wizard into an Ajaxflow

Location:
trunk
Files:
20 added
11 modified

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}