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

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