source: trunk/grails-app/controllers/dbnp/importer/ImporterController.groovy @ 660

Last change on this file since 660 was 660, checked in by keesvb, 11 years ago

updated importer logic to fetch template field type from importer mapping instead of excel type guessing

  • Property svn:keywords set to Date Author Rev
File size: 9.5 KB
Line 
1/**
2 * Importer controller
3 *
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 *
15 * Revision information:
16 * $Rev: 660 $
17 * $Author: keesvb $
18 * $Date: 2010-07-19 10:37:23 +0000 (ma, 19 jul 2010) $
19 */
20
21package dbnp.importer
22
23import dbnp.studycapturing.Template
24import dbnp.studycapturing.Study
25import dbnp.studycapturing.Subject
26import dbnp.studycapturing.Event
27
28import dbnp.studycapturing.Sample
29import dbnp.studycapturing.TemplateFieldType
30import dbnp.studycapturing.TemplateField
31import grails.converters.JSON
32import org.apache.poi.hssf.usermodel.HSSFWorkbook
33
34class ImporterController {
35    def ImporterService   
36
37    /**
38     * Default page
39     **/
40    def index = {       
41    }
42
43    def simpleWizard = {
44        render(view:"index_simple", model:[studies:Study.list(), entities: grailsApplication.config.gscf.domain.importableEntities])
45    }
46
47    def advancedWizard = {
48        render(view:"index_advanced", model:[templates:Template.list()])
49    }
50
51    /**
52    * This method will move the uploaded file to a temporary path and send the header
53    * and the first n rows to the preview
54    * @param importfile uploaded file to import
55    * @param study.id study identifier
56    */
57    def upload_advanced = {
58        def wb = handleUpload('importfile')
59
60        session.importer_header = ImporterService.getHeader(wb, 0)
61        session.importer_study = Study.get(params.study.id.toInteger())
62        session.importer_template_id = params.template_id
63        session.importer_workbook = wb
64
65        render (view:"step1_advanced", model:[header:session.importer_header, datamatrix:ImporterService.getDatamatrix(wb, session.importer_header, 0, 5)])
66    }
67
68    /**
69    * This method will move the uploaded file to a temporary path and send the header
70    * and the rows to the postview
71    *
72    * @param importfile uploaded file to import
73    * @param entity string representation of the entity chosen
74    */
75    def upload_simple = {
76        def wb = handleUpload('importfile')
77        def selectedentities = []
78        def entity = grailsApplication.config.gscf.domain.importableEntities.get(params.entity).entity
79        def entityClass = Class.forName(entity, true, this.getClass().getClassLoader())
80
81        session.importer_header = ImporterService.getHeader(wb, 0, entityClass)
82        session.importer_study = Study.get(params.study.id.toInteger())
83        session.importer_template_id = params.template_id
84        session.importer_workbook = wb
85
86        session.importer_header.each {     
87            selectedentities.add([name:params.entity, columnindex:it.key.toInteger()])
88        }
89
90        def templates = Template.get(session.importer_template_id)
91       
92        render(view:"step2_simple", model:[entities: selectedentities, header:session.importer_header, datamatrix:ImporterService.getDatamatrix(wb, session.importer_header, 0, 5), templates:templates])
93    }
94
95    /**
96     * This method handles a file being uploaded and storing it in a temporary directory
97     * and returning a workbook
98     *
99     * @param formfilename name used for the file field in the form
100     * @return workbook object reference
101     */
102    private HSSFWorkbook handleUpload(formfilename) {
103
104        def downloadedfile = request.getFile(formfilename);
105        def tempfile = new File(System.getProperty('java.io.tmpdir') + File.separatorChar + System.currentTimeMillis() + ".nmcdsp")
106        downloadedfile.transferTo(tempfile)
107
108        return ImporterService.getWorkbook(new FileInputStream(tempfile))
109    }
110
111    /**
112     * @param entity entity class we are using (dbnp.studycapturing.Subject etc.)
113     */
114
115    def saveMissingProperties = {
116        println params.entity
117       
118        session.importer_importeddata.each { table ->
119            table.each { entity ->
120                entity.giveFields().each { field ->
121                    print ":" + params["entity_" + entity.hashCode() + "_" + field.escapedName()]
122                    entity.setFieldValue (field.toString(), params["entity_" + entity.hashCode() + "_" + field.escapedName()])
123                }               
124            }
125        }
126
127        render(view:"step3", model:[datamatrix:session.importer_importeddata]) 
128    }
129
130    /**
131    * User has assigned all entities and templatefieldtypes to the columns and continues to the next step (assigning properties to columns)
132    * All information of the columns is stored in a session as MappingColumn object
133    *
134    * @param entities list of entities and columns it has been assigned to (columnindex.entitytype)
135    * @param templatefieldtype list of celltypes and columns it has been assigned to (columnindex:templatefieldtype format)
136    * @return properties page
137    *
138    * @see celltype: http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html
139    */
140    def savePreview = {
141        def tft = null 
142        def identifiercolumnindex = (params.identifier!=null) ? params.identifier.toInteger() : -1
143        def selectedentities = []
144
145        // loop all entities and see which column has been assigned which entitytype
146        // and build an array containing the selected entities
147        params.entity.index.each { columnindex, entityname ->
148            def _entity = [name:entityname,columnindex:columnindex.toInteger()]
149            selectedentities.add(_entity)
150        }
151
152        params.templatefieldtype.index.each { columnindex, _templatefieldtype ->
153            switch (_templatefieldtype) {
154                case "STRING"       : tft = TemplateFieldType.STRING
155                                      break
156                case "TEXT"         : tft = TemplateFieldType.TEXT
157                                      break
158                case "INTEGER"      : tft = TemplateFieldType.INTEGER
159                                      break
160                case "FLOAT"        : tft = TemplateFieldType.FLOAT
161                                      break
162                case "DOUBLE"       : tft = TemplateFieldType.DOUBLE
163                                      break
164                case "STRINGLIST"   : tft = TemplateFieldType.STRINGLIST
165                                      break
166                case "ONTOLOGYTERM" : tft = TemplateFieldType.ONTOLOGYTERM
167                                      break
168                case "DATE"         : tft = TemplateFieldType.DATE
169                                      break
170                default: break
171            }
172           
173            session.importer_header[columnindex.toInteger()].templatefieldtype = tft
174        }
175
176        params.entity.index.each { columnindex, entityname ->
177            Class clazz = null
178
179            switch (entityname) {
180                case "Study"    : clazz = dbnp.studycapturing.Study
181                        break
182                case "Subject"  : clazz = dbnp.studycapturing.Subject
183                        break
184                case "Event"    : clazz = dbnp.studycapturing.Event
185                        break
186                case "Protocol" : clazz = dbnp.studycapturing.Protocol
187                        break
188                case "Sample"   : clazz = dbnp.studycapturing.Sample
189                        break
190                default: clazz = Object
191                        break
192            }
193
194            session.importer_header[columnindex.toInteger()].identifier = (columnindex.toInteger() == identifiercolumnindex) ? true : false
195            session.importer_header[columnindex.toInteger()].index = columnindex.toInteger()
196            session.importer_header[columnindex.toInteger()].entity = clazz
197        }
198
199        // currently only one template is used for all entities
200        // TODO: show template fields per entity
201       
202        def templates = Template.get(session.importer_template_id)
203
204        render(view:"step2", model:[entities:selectedentities, header:session.importer_header, templates:templates])
205    }
206
207    /**
208    * @param columnproperty array of columns containing index and property (represented as a String)
209    *
210    */
211    def saveProperties = {
212
213        // Find actual Template object from the chosen template name
214        def template = Template.get(session.imported_template_id)
215
216        params.columnproperty.index.each { columnindex, property ->
217
218                // Create an actual class instance of the selected entity with the selected template
219                // This should be inside the closure because in some cases in the advanced importer, the fields can have different target entities
220                def entityClass = Class.forName(session.importer_header[columnindex.toInteger()].entity.getName(), true, this.getClass().getClassLoader())
221                def entityObj = entityClass.newInstance(template:template)
222
223                // Store the selected property for this column into the column map for the ImporterService
224                session.importer_header[columnindex.toInteger()].property = property
225                // Look up the template field type of the target TemplateField and store it also in the map
226                session.importer_header[columnindex.toInteger()].templatefieldtype = entityObj.giveFields()[property].type
227
228                //if it's an identifier set the mapping column true or false
229                entityObj.giveFields().each {
230                    (it.preferredIdentifier && (it.name==property)) ? session.importer_header[columnindex.toInteger()].identifier = true : false
231                }
232        }
233
234        //import workbook
235        session.importer_importeddata = ImporterService.importdata(session.importer_template_id, session.importer_workbook, 0, 1, session.importer_header)
236
237        if (params.layout=="horizontal")
238            render(view:"step3_simple", model:[datamatrix:session.importer_importeddata])
239        else if (params.layout=="vertical")
240            render(view:"step3", model:[datamatrix:session.importer_importeddata])
241    }
242
243    def savePostview = {
244        ImporterService.saveDatamatrix(session.importer_study, session.importer_importeddata)
245        render(view:"step4")
246    }
247
248    /**
249    * Return templates which belong to a certain entity type
250    *
251    * @param entity entity name string (Sample, Subject, Study et cetera)
252    * @return JSON object containing the found templates
253    */
254    def ajaxGetTemplatesByEntity = {
255        def entityClass = grailsApplication.config.gscf.domain.importableEntities.get(params.entity).entity
256       
257
258        // fetch all templates for a specific entity
259        //def templates = Template.findAllByEntity(Class.forName(entityClass, true, this.getClass().getClassLoader()))
260        def templates = Template.list()
261
262        println templates.dump()
263
264        // render as JSON
265        render templates as JSON
266    }
267}
Note: See TracBrowser for help on using the repository browser.