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

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