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

Last change on this file since 738 was 738, checked in by tabma, 11 years ago
  • fixed sheetindex argument
  • Property svn:keywords set to Date Author Rev
File size: 10.6 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: 738 $
17 * $Author: tabma $
18 * $Date: 2010-07-28 07:53:17 +0000 (wo, 28 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        // Initialize some session variables
82        session.importer_workbook = wb
83        session.importer_study = Study.get(params.study.id.toInteger())
84        session.importer_template_id = params.template_id
85        session.importer_sheetindex = params.sheetindex.toInteger() -1 // 0 == first sheet
86        session.importer_datamatrix_start = params.datamatrix_start.toInteger() -1 // 0 == first row
87        session.importer_headerrow = params.headerrow.toInteger()
88
89        // Get the header from the Excel file using the arguments given in the first step of the wizard
90        session.importer_header = ImporterService.getHeader(wb,
91                                                            session.importer_sheetindex,
92                                                            session.importer_headerrow,
93                                                            session.importer_datamatrix_start,
94                                                            entityClass)
95       
96        // Initialize 'selected entities', used to show entities above the columns
97        session.importer_header.each {
98            selectedentities.add([name:params.entity, columnindex:it.key.toInteger()])
99        }
100
101        def templates = Template.get(session.importer_template_id)
102       
103        render(view:"step2_simple", model:[entities: selectedentities,
104                                           header:session.importer_header,
105                                           datamatrix:ImporterService.getDatamatrix(
106                                               wb, session.importer_header,
107                                               session.importer_sheetindex,
108                                               session.importer_datamatrix_start,
109                                               5),
110                                           templates:templates])
111    }
112
113    /**
114     * This method handles a file being uploaded and storing it in a temporary directory
115     * and returning a workbook
116     *
117     * @param formfilename name used for the file field in the form
118     * @return workbook object reference
119     */
120    private HSSFWorkbook handleUpload(formfilename) {
121
122        def downloadedfile = request.getFile(formfilename);
123        def tempfile = new File(System.getProperty('java.io.tmpdir') + File.separatorChar + System.currentTimeMillis() + ".nmcdsp")
124        downloadedfile.transferTo(tempfile)
125
126        return ImporterService.getWorkbook(new FileInputStream(tempfile))
127    }
128
129    /**
130     * Method to save the missing properties
131     * @param entity entity class we are using (dbnp.studycapturing.Subject etc.)
132     */
133
134    def saveMissingProperties = {
135
136        session.importer_importeddata.each { table ->
137            table.each { entity ->
138                entity.giveFields().each { field ->
139                    //print ":" + params["entity_" + entity.hashCode() + "_" + field.escapedName()]
140                    entity.setFieldValue (field.toString(), params["entity_" + entity.hashCode() + "_" + field.escapedName()])
141                }               
142            }
143        }
144
145        render(view:"step3", model:[datamatrix:session.importer_importeddata]) 
146    }
147
148    /**
149    * User has assigned all entities and templatefieldtypes to the columns and continues to the next step (assigning properties to columns)
150    * All information of the columns is stored in a session as MappingColumn object
151    *
152    * @param entities list of entities and columns it has been assigned to (columnindex.entitytype)
153    * @param templatefieldtype list of celltypes and columns it has been assigned to (columnindex:templatefieldtype format)
154    * @return properties page
155    *
156    * @see celltype: http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html
157    */
158    def savePreview = {
159        def tft = null 
160        def identifiercolumnindex = (params.identifier!=null) ? params.identifier.toInteger() : -1
161        def selectedentities = []
162
163        // loop all entities and see which column has been assigned which entitytype
164        // and build an array containing the selected entities
165        params.entity.index.each { columnindex, entityname ->
166            def _entity = [name:entityname,columnindex:columnindex.toInteger()]
167            selectedentities.add(_entity)
168        }
169
170        params.templatefieldtype.index.each { columnindex, _templatefieldtype ->
171            switch (_templatefieldtype) {
172                case "STRING"       : tft = TemplateFieldType.STRING
173                                      break
174                case "TEXT"         : tft = TemplateFieldType.TEXT
175                                      break
176                case "INTEGER"      : tft = TemplateFieldType.INTEGER
177                                      break
178                case "FLOAT"        : tft = TemplateFieldType.FLOAT
179                                      break
180                case "DOUBLE"       : tft = TemplateFieldType.DOUBLE
181                                      break
182                case "STRINGLIST"   : tft = TemplateFieldType.STRINGLIST
183                                      break
184                case "ONTOLOGYTERM" : tft = TemplateFieldType.ONTOLOGYTERM
185                                      break
186                case "DATE"         : tft = TemplateFieldType.DATE
187                                      break
188                default: break
189            }
190           
191            // Set the templatefield type for this column
192            session.importer_header[columnindex.toInteger()].templatefieldtype = tft
193        }
194
195        // Detect the entity type
196        params.entity.index.each { columnindex, entityname ->
197            Class clazz = null
198
199            switch (entityname) {
200                case "Study"    : clazz = dbnp.studycapturing.Study
201                        break
202                case "Subject"  : clazz = dbnp.studycapturing.Subject
203                        break
204                case "Event"    : clazz = dbnp.studycapturing.Event
205                        break
206                case "Protocol" : clazz = dbnp.studycapturing.Protocol
207                        break
208                case "Sample"   : clazz = dbnp.studycapturing.Sample
209                        break
210                default: clazz = Object
211                        break
212            }
213
214            // Store properties for this column
215            session.importer_header[columnindex.toInteger()].identifier = (columnindex.toInteger() == identifiercolumnindex) ? true : false
216            session.importer_header[columnindex.toInteger()].index = columnindex.toInteger()
217            session.importer_header[columnindex.toInteger()].entity = clazz
218        }
219
220        // currently only one template is used for all entities
221        // TODO: show template fields per entity
222       
223        def templates = Template.get(session.importer_template_id)
224
225        render(view:"step2", model:[entities:selectedentities, header:session.importer_header, templates:templates])
226    }
227
228    /**
229    * @param columnproperty array of columns containing index and property (represented as a String)
230    *
231    */
232    def saveProperties = {
233
234        // Find actual Template object from the chosen template name
235        def template = Template.get(session.importer_template_id)
236
237        params.columnproperty.index.each { columnindex, property ->
238
239                // Create an actual class instance of the selected entity with the selected template
240                // This should be inside the closure because in some cases in the advanced importer, the fields can have different target entities
241                def entityClass = Class.forName(session.importer_header[columnindex.toInteger()].entity.getName(), true, this.getClass().getClassLoader())
242                def entityObj = entityClass.newInstance(template:template)
243
244                // Store the selected property for this column into the column map for the ImporterService
245                session.importer_header[columnindex.toInteger()].property = property
246
247                // Look up the template field type of the target TemplateField and store it also in the map
248                session.importer_header[columnindex.toInteger()].templatefieldtype = entityObj.giveFieldType(property)
249
250                // Is a "Don't import" property assigned to the column?
251                session.importer_header[columnindex.toInteger()].dontimport = (property=="dontimport") ? true : false
252
253                //if it's an identifier set the mapping column true or false
254                entityObj.giveFields().each {
255                    (it.preferredIdentifier && (it.name==property)) ? session.importer_header[columnindex.toInteger()].identifier = true : false
256                }
257        }
258
259        //import workbook
260        session.importer_importeddata = ImporterService.importdata(session.importer_template_id, session.importer_workbook, 0, 1, session.importer_header)
261
262        if (params.layout=="horizontal")
263            render(view:"step3_simple", model:[datamatrix:session.importer_importeddata])
264        else if (params.layout=="vertical")
265            render(view:"step3", model:[datamatrix:session.importer_importeddata])
266    }
267
268    /**
269     * Method which saves the data matrix to the database
270     */
271    def savePostview = {
272        def validatedSuccesfully = ImporterService.saveDatamatrix(session.importer_study, session.importer_importeddata)
273        render(view:"step4", model:[validatedSuccesfully:validatedSuccesfully, totalrows:session.importer_importeddata.size])
274    }
275
276    /**
277    * Return templates which belong to a certain entity type
278    *
279    * @param entity entity name string (Sample, Subject, Study et cetera)
280    * @return JSON object containing the found templates
281    */
282    def ajaxGetTemplatesByEntity = {
283        def entityClass = grailsApplication.config.gscf.domain.importableEntities.get(params.entity).entity
284       
285
286        // fetch all templates for a specific entity
287        def templates = Template.findAllByEntity(Class.forName(entityClass, true, this.getClass().getClassLoader()))   
288
289        // render as JSON
290        render templates as JSON
291    }
292}
Note: See TracBrowser for help on using the repository browser.