root/grails-app/controllers/importer/MeasurementTypeImporterController.groovy @ 151

Revision 151, 9.3 KB (checked in by adem.bilican@…, 4 years ago)

Catching exceptions for file errors

Line 
1package importer
2import data.SimpleAssayMeasurementType
3import data.*
4
5import org.apache.poi.hssf.usermodel.*
6import org.apache.poi.poifs.filesystem.POIFSFileSystem
7import org.apache.poi.ss.usermodel.DataFormatter
8import org.apache.poi.hssf.usermodel.HSSFWorkbook
9import org.apache.commons.codec.*
10
11/**
12 * @author Adem and Jahn
13 * @since 20100602
14 */
15
16class MeasurementTypeImporterController {
17
18    def ImporterService
19    def searchableService
20    def fileService
21
22    def index = {
23        String.metaClass.mostSimilarTo = { mostSimilar(delegate, it) }
24        redirect(action: 'pages')
25    }
26
27    def pagesFlow = {
28
29        onStart {
30            flow.page = 0
31            flow.pages = [
32                [title: 'Import data'],
33                [title: 'Show data'],
34                [title: 'Done']
35            ]
36        }
37
38        mainPage {
39            render(view:'/measurementTypeImporter/importMain')
40            onRender {
41                flow.page=0
42                next()
43            }
44            on("next"){
45                success()
46            }.to"importData"
47        }
48
49        importData{
50            render(view:'_importData')
51            onRender {
52                flow.page=1
53            }
54            on('next'){
55                flash.errors = false
56                def tabbedTable = params['measurementTypeData']
57                // there is user input in the text area
58                if( (tabbedTable.replaceAll("^\\s+", "").size() > 0) && (params['file'] == "null" ) ) {   
59                    flow.tab = tabbedTable
60                    try {
61                        this.parseData(ImporterService, flow.tab, flow)
62                        flow.file = params['file']
63                        success()
64                    }
65                    catch (Exception e) {
66                        flash.errors = "Input Error : Please check your input data"
67                        error()
68                    }
69                }
70                // there is a file
71                else if ((tabbedTable.replaceAll("^\\s+", "").size() == 0) && (params['file'] != "null" )) {
72                    try{
73                        this.parseData(ImporterService, fileService.get(params['file']) ,flow)
74                        flow.file = params['file']
75                        success()
76                    }
77                    catch (Exception e){
78                        flash.errors = "File Error : Please check the file integrity"
79                        error()
80                    }
81                }
82                // catch error if there is nothing to do
83                else if ((tabbedTable.replaceAll("^\\s+", "").size() == 0) && (params['file'] == "null" ))
84                {
85                    flash.errors = 'No user input : Please paste your data or select a file'
86                    error()
87                }
88                //catch error if there is too much information
89                else if ((tabbedTable.replaceAll("^\\s+", "").size() > 0) && (params['file'] != "null" ))
90                {
91                    flash.errors = 'Too much information : Please paste your data OR select a file'
92                    error()
93                }
94            }.to('showData')
95        }
96
97        showData{
98            render(view:'_showData')
99            onRender{
100                flow.page=2
101            }
102            on('next'){
103                flash.errors=false
104                try {
105                    this.isValid(params['att'],flow.datamatrix,flash,flow)
106                    fileService.delete(flow.file)
107                    success()
108
109                }
110                catch (Exception e) {
111                    flash.errors = 'Error : Please check your selection'
112                    fileService.delete(flow.file)
113                    error()
114                }
115            }.to('done')
116            on('previous').to('importData')
117        }
118
119        done {
120            render(view:'_done')
121            onRender {
122                flow.page=3
123            }
124        }
125    }
126
127    /*
128     * parseData will parse the pasted tab-delimited data
129     */
130    def parseData(ImporterService, tabDelimited, flow){
131        def headersList= []
132        def datamatrix = []
133        def wb = getWorkBook(tabDelimited)
134        // getHeader contains information about headers
135        for (header in ImporterService.getHeader(wb, 0)){
136            headersList.add(header.name)
137        }
138        // getDatamatrix contains the data for each line
139        for (line in ImporterService.getDatamatrix(wb,0,5,1)){
140            def lines = []
141            for (box in line ){
142                lines.add(box.toString())
143            }
144            datamatrix.add(lines)
145        }
146        flow.datamatrix = datamatrix
147        flow.headers = headersList
148    }
149
150    /* Create a Horrible Style Sheet Framework Workbook from tab-delimited string.
151     *
152     * @param  tabbed:  A tab-delimited string representing a table as by copy and paste from
153     *                  an Excell sheet.
154     * @return HSSFWorkbook containing the same table.
155     *
156     */
157    private HSSFWorkbook getWorkBook( tabbed ) {
158        def wb
159        if ( tabbed instanceof File ){
160            def fs = new POIFSFileSystem(new FileInputStream(tabbed))
161            wb = new HSSFWorkbook(fs)
162        }
163        else {
164            wb = new HSSFWorkbook()
165        }
166        def createHelper = wb.getCreationHelper()
167        def sheet = wb.createSheet("sheet")
168
169        def rowIndex = 0
170        tabbed.splitEachLine("\t") { line ->
171            def row = sheet.createRow((short)rowIndex++)
172            def colIndex = 0
173            line.each{ entry ->
174                def cell = row.createCell(colIndex++).setCellValue(entry)
175            }
176        }
177        return wb
178    }
179
180    // validate the measurementst type before adding to the database
181    private isValid(attributes,datamatrix,flash,flow) {
182        def errors=false
183        def matrixToSave = [:]
184        def errorList = []
185        for(i in 0..attributes.size()-1){
186            def dataList= []
187            for (j in datamatrix){
188                dataList.add(j.getAt(i))
189            }
190            matrixToSave[attributes.getAt(i)] = dataList
191        }
192
193        for (i in 0..datamatrix.size()-1){
194
195            def typeExists = SimpleAssayMeasurementType.find("from SimpleAssayMeasurementType t where t.name='${matrixToSave.getAt("Name").getAt(i).toString()}'")
196
197            if (typeExists){
198                errorList.add(typeExists.name)
199            }
200            else {
201                def measurementType = new SimpleAssayMeasurementType(
202                    name: matrixToSave.getAt("Name").getAt(i).toString(),
203                    unit: (matrixToSave.getAt("Unit")!=null) ? matrixToSave.getAt("Unit").getAt(i).toString() : null,
204                    detectableLimit: (matrixToSave.getAt("Detectable Limit")!=null) ? matrixToSave.getAt("Detectable Limit").getAt(i).replaceAll(",",".").toFloat() : "0" ,
205                    referenceValues: (matrixToSave.getAt("Reference Values")!=null) ? matrixToSave.getAt("Reference Values").getAt(i).toString() : null ,
206                    isNew : ((matrixToSave.getAt("Is New")!=null) && (matrixToSave.getAt("Is New").getAt(i).toString()=="yes")) ? true : false ,
207                    isIntake : ((matrixToSave.getAt("Is Intake")!=null) && (matrixToSave.getAt("Is Intake").getAt(i).toString()=="yes")) ? true : false ,
208                    inSerum : ((matrixToSave.getAt("In Serum")!=null) && (matrixToSave.getAt("In Serum").getAt(i).toString()=="yes")) ? true : false ,
209                    isDrug : ((matrixToSave.getAt("Is Drug")!=null) && (matrixToSave.getAt("Is Drug").getAt(i).toString()=="yes")) ? true : false
210                )
211                measurementType.save(flush:true)
212            }
213
214        }
215        flow.errorList = errorList
216        if (errors){
217            flash.errors = "<html>The measurements type "+errorList+" already exists<br> Please edit your data </html>"
218        }
219        return !errors
220    }
221
222    // classes for fuzzy string matching
223    // <FUZZY MATCHING>
224    static def similarity(l_seq, r_seq, degree=2) {
225        def l_histo = countNgramFrequency(l_seq, degree)
226        def r_histo = countNgramFrequency(r_seq, degree)
227
228        dotProduct(l_histo, r_histo) /
229        Math.sqrt(dotProduct(l_histo, l_histo) *
230            dotProduct(r_histo, r_histo))
231    }
232
233    static def countNgramFrequency(sequence, degree) {
234        def histo = [:]
235        def items = sequence.size()
236
237        for (int i = 0; i + degree <= items; i++)
238        {
239            def gram = sequence[i..<(i + degree)]
240            histo[gram] = 1 + histo.get(gram, 0)
241        }
242        histo
243    }
244
245    static def dotProduct(l_histo, r_histo) {
246        def sum = 0
247        l_histo.each { key, value ->
248            sum = sum + l_histo[key] * r_histo.get(key, 0)
249        }
250        sum
251    }
252
253    static def stringSimilarity (l_str, r_str, degree=2) {
254        similarity(l_str.toLowerCase().toCharArray(),
255            r_str.toLowerCase().toCharArray(),
256            degree)
257    }
258
259    static def mostSimilar(pattern, candidates, threshold=0) {
260        def topScore = 0
261        def bestFit = null
262
263        candidates.each { candidate ->
264            def score = stringSimilarity(pattern, candidate)
265            if (score > topScore) {
266                topScore = score
267                bestFit = candidate
268            }
269        }
270
271        if (topScore < threshold)
272        bestFit = null
273
274        bestFit
275    }
276    // </FUZZY MATCHING>
277
278
279}
280
Note: See TracBrowser for help on using the browser.