source: trunk/grails-app/services/dbnp/importer/ImporterService.groovy @ 350

Last change on this file since 350 was 350, checked in by keesvb, 9 years ago

added ontology/term properties, getting code to work from clean build: removed Protocol and EventDescription? controllers, cleaned up Protocol code from ImporterService?, commented out EventDescription? code in WizardController?

  • Property svn:keywords set to Author Rev Date
File size: 10.6 KB
Line 
1/**
2 * Importer service
3 *
4 * The importer service handles the import of tabular, comma delimited and Excel format
5 * based files.
6 *
7 * @package     importer
8 * @author      t.w.abma@umcutrecht.nl
9 * @since       20100126
10 *
11 * Revision information:
12 * $Rev: 350 $
13 * $Author: keesvb $
14 * $Date: 2010-04-19 13:45:35 +0000 (ma, 19 apr 2010) $
15 */
16
17package dbnp.importer
18import org.apache.poi.hssf.usermodel.*
19import org.apache.poi.poifs.filesystem.POIFSFileSystem
20import org.apache.poi.ss.usermodel.DataFormatter
21
22import dbnp.studycapturing.TemplateFieldType
23import dbnp.studycapturing.Template
24import dbnp.studycapturing.Study
25import dbnp.studycapturing.Subject
26import dbnp.studycapturing.Event
27
28import dbnp.studycapturing.Sample
29
30import dbnp.data.Term
31
32class ImporterService {
33
34    boolean transactional = true
35
36    /**
37    * @param is input stream representing the (workbook) resource
38    * @return high level representation of the workbook
39    */
40    HSSFWorkbook getWorkbook(InputStream is) {
41        POIFSFileSystem fs = new POIFSFileSystem(is)
42        HSSFWorkbook    wb = new HSSFWorkbook(fs);
43        return wb;
44    }
45
46    /**
47     * @param wb high level representation of the workbook
48     * @return header representation as a MappingColumn hashmap
49     */
50    def getHeader(HSSFWorkbook wb, int sheetindex){
51
52        def sheet = wb.getSheetAt(sheetindex)
53        def datamatrix_start = sheet.getFirstRowNum() + 1
54        //def header = []
55        def header = [:]
56        def df = new DataFormatter()
57
58
59        for (HSSFCell c: sheet.getRow(datamatrix_start)) {
60            def index   =   c.getColumnIndex()
61            def datamatrix_celltype = sheet.getRow(datamatrix_start).getCell(index).getCellType()
62            def headercell = sheet.getRow(sheet.getFirstRowNum()).getCell(index)
63
64            // Check for every celltype, currently redundant code, but possibly this will be
65            // a piece of custom code for every cell type like specific formatting
66               
67            switch (datamatrix_celltype) {
68                    case HSSFCell.CELL_TYPE_STRING:
69                            header[index] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell), templatefieldtype:TemplateFieldType.STRING, index:index);
70                            break
71                    case HSSFCell.CELL_TYPE_NUMERIC:                   
72                            if (HSSFDateUtil.isCellDateFormatted(c)) {
73                                header[index] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell), templatefieldtype:TemplateFieldType.DATE, index:index)
74                            }
75                            else
76                                header[index] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell), templatefieldtype:TemplateFieldType.INTEGER,index:index);
77                            break
78                    case HSSFCell.CELL_TYPE_BLANK:
79                            header[index] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell), templatefieldtype:TemplateFieldType.STRING, index:index);
80                            break
81                    default:
82                            header[index] = new dbnp.importer.MappingColumn(name:df.formatCellValue(headercell), templatefieldtype:TemplateFieldType.STRING,index:index);
83                            break
84            }
85        }
86        return header
87    }
88
89    /**
90     * This method is meant to return a matrix of the rows and columns
91     * used in the preview
92     *
93     * @param wb workbook object
94     * @param sheetindex sheet index used
95     * @param rows amount of rows returned
96     * @return two dimensional array (matrix) of HSSFCell objects
97     */
98
99    HSSFCell[][] getDatamatrix(HSSFWorkbook wb, int sheetindex, int count) {
100        def sheet = wb.getSheetAt(sheetindex)
101        def rows  = []
102        def df = new DataFormatter()
103        def datamatrix_start = 1
104
105        // walk through all rows
106        (count <= sheet.getLastRowNum()) ?
107        ((datamatrix_start+sheet.getFirstRowNum())..count).each { rowindex ->
108            def row = []
109
110            // walk through every cell
111            for (HSSFCell c: sheet.getRow(rowindex))
112                row.add(c)
113                //row.add(df.formatCellValue(c))
114            rows.add(row)
115        } : 0
116
117        return rows
118    }
119
120    /**
121    * This method will move a file to a new location.
122    *
123    * @param file File object to move
124    * @param folderpath folder to move the file to
125    * @param filename (new) filename to give
126    * @return if file has been moved succesful, the new path and filename will be returned, otherwise an empty string will be returned
127    */
128    def moveFile(File file, String folderpath, String filename) {
129        try {
130                def rnd = ""; //System.currentTimeMillis()
131                file.transferTo(new File(folderpath, rnd+filename))
132                return folderpath + filename
133            } catch(Exception exception) {
134                log.error "File move error, ${exception}"
135                return ""
136                }
137    }
138
139    /**
140    * @return random numeric value
141    */
142    def random = {
143            return System.currentTimeMillis() + Runtime.runtime.freeMemory()
144        }
145
146    /**
147    * Method to read data from a workbook and to import data into the database
148    * by using mapping information
149    *
150    * @param template_id template identifier to use fields from
151    * @param wb POI horrible spreadsheet formatted workbook object
152    * @param mcmap linked hashmap (preserved order) of MappingColumns
153    * @param sheetindex sheet to use when using multiple sheets
154    * @param rowindex first row to start with reading the actual data (NOT the header)
155    * @return two dimensional array containing records (with entities)
156    *
157    * @see dbnp.importer.MappingColumn
158    */
159    def importdata(template_id, HSSFWorkbook wb, int sheetindex, int rowindex, mcmap) {
160        def sheet = wb.getSheetAt(sheetindex)
161        def table = []
162       
163        // walk through all rows       
164        (rowindex..sheet.getLastRowNum()).each { i ->
165            table.add(createRecord(template_id, sheet.getRow(i), mcmap))           
166        }
167
168        /*table.each {
169            it.each { entity ->
170                entity.giveFields().each { field ->
171                    print field.name + ":" + entity.getFieldValue(field.name) + "/"
172                }
173                println
174            }
175        }*/
176
177        return table   
178    }
179   
180     /**
181                     // start transaction
182                        def transaction = sessionFactory.getCurrentSession().beginTransaction()
183                              // persist data to the database
184                                try {
185                                   // commit transaction
186                                        println "commit"
187                                        transaction.commit()
188                                        success()
189                                } catch (Exception e) {
190                                        // rollback
191                                        // stacktrace in flash scope
192                                        flash.debug = e.getStackTrace()
193
194                                        println "rollback"
195                                        transaction.rollback()
196                                        error()
197                                }
198      */
199
200    /**
201     * Method to store a matrix containing the entities in a record like structure. Every row in the table
202     * contains one or more entity objects (which contain fields with values). So actually a row represents
203     * a record with fields from one or more different entities.
204     *
205     * @param study entity Study
206     * @param datamatrix two dimensional array containing entities with values read from Excel file     *
207     */   
208    def savedata(Study study, datamatrix) {
209        study.refresh()
210       
211        datamatrix.each { record ->
212            record.each { entity ->
213                switch (entity.getClass()) {
214                    case Study   :  print "Persisting Study `" + entity.title + "`: "
215                                    persistEntity(entity)
216                                    break
217                    case Subject :  print "Persisting Subject `" + entity.name + "`: "                             
218                                    persistEntity(entity)                                   
219                                    study.addToSubjects(entity)
220                                    break
221                    case Event   :  print "Persisting Event `" + entity.eventdescription + "`: "
222                                    persistEntity(entity)
223                                    break
224                    case Sample  :  print "Persisting Sample `" + entity.name +"`: "
225                                    persistEntity(entity)
226                                    break
227                    default      :  println "Skipping persisting of `" + entity.getclass() +"`"
228                                    break
229                }
230            }
231        }
232    }
233
234    /**
235     * Method to persist entities into the database
236     *
237     * @param entity entity object like Study, Subject, Protocol et cetera
238     *
239     */
240    def persistEntity(entity) { 
241        if (entity.save(flush:true)) {  //.merge?           
242        } else entity.errors.allErrors.each {
243                println it
244        }
245    }
246
247    /**
248     * This method creates a record (array) containing entities with values
249     *
250     * @param template_id template identifier
251     * @param excelrow POI based Excel row containing the cells
252     * @param mcmap map containing MappingColumn objects
253     */
254    def createRecord(template_id, HSSFRow excelrow, mcmap) {
255        def df = new DataFormatter()
256        def template = Template.get(template_id)
257        def record = [] 
258       
259        def study = new Study(title:"New study", template:template)
260        def subject = new Subject(name:"New subject", species:Term.findByName("Homo sapiens"), template:template)
261        def event = new Event(eventdescription:"New event", template:template)
262        def sample = new Sample(name:"New sample", template:template)
263
264        for (HSSFCell cell: excelrow) {
265            def mc = mcmap[cell.getColumnIndex()]
266            def value = formatValue(df.formatCellValue(cell), mc.templatefieldtype)         
267
268            switch(mc.entity) {
269                case Study      :   (record.any {it.getClass()==mc.entity}) ? 0 : record.add(study)
270                                    if (mc.identifier) { study.title = value; break }
271                                    study.setFieldValue(mc.property.name, value)
272                                    break
273                case Subject    :   (record.any {it.getClass()==mc.entity}) ? 0 : record.add(subject)
274                                    if (mc.identifier) { subject.name = value; break }
275                                    subject.setFieldValue(mc.property.name, value)                                 
276                                    break
277                case Event      :   (record.any {it.getClass()==mc.entity}) ? 0 : record.add(event)
278                                    if (mc.identifier) { event.eventdescription = value; break }
279                                    event.setFieldValue(mc.property.name, value)
280                                    break
281                case Sample     :   (record.any {it.getClass()==mc.entity}) ? record.add(sample) : 0
282                                    if (mc.identifier) { sample.name = value; break }
283                                    sample.setFieldValue(mc.property.name, value)
284                                    break
285                case Object     :   // don't import
286                                    break
287            } // end switch
288        } // end for
289
290        return record
291    }
292
293    /**
294    * Method to parse a value conform a specific type
295    * @param value string containing the value
296    * @return object corresponding to the TemplateFieldType
297    */
298    def formatValue(String value, TemplateFieldType type) {     
299        switch (type) {
300            case TemplateFieldType.STRING       :   return value.trim()
301            case TemplateFieldType.TEXT         :   return value.trim()
302            case TemplateFieldType.INTEGER      :   return Integer.valueOf(value.replaceAll("[^0-9]",""))
303            case TemplateFieldType.FLOAT        :   return Float.valueOf(value.replace(",","."));
304            case TemplateFieldType.DOUBLE       :   return Double.valueOf(value.replace(",","."));
305            case TemplateFieldType.STRINGLIST   :   return value.trim()
306            case TemplateFieldType.ONTOLOGYTERM :   return value.trim()
307            case TemplateFieldType.DATE         :   return value
308            default                             :   return value
309        }
310    }
311}
Note: See TracBrowser for help on using the repository browser.