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

Revision 181, 9.4 KB (checked in by adem.bilican@…, 3 years ago)

adding file error handling

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