Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
package edu.ncsu.csc.itrust.action;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import edu.ncsu.csc.itrust.beans.CDCStatsBean;
import edu.ncsu.csc.itrust.dao.DAOFactory;
import edu.ncsu.csc.itrust.dao.mysql.CDCBmiStatsDAO;
import edu.ncsu.csc.itrust.dao.mysql.CDCHeadCircStatsDAO;
import edu.ncsu.csc.itrust.dao.mysql.CDCHeightStatsDAO;
import edu.ncsu.csc.itrust.dao.mysql.CDCStatsDAO;
import edu.ncsu.csc.itrust.dao.mysql.CDCWeightStatsDAO;
import edu.ncsu.csc.itrust.exception.DBException;
/**
* UploadReferenceTablesAction is an action class that is used for uploading reference tables. It reads
* in csv files and parses and loads them to a specified reference table. Contains methods for storing
* csv files for weight, height, bmi, and head circumference statistics. Each store method also verifies
* whether the passed in file is correctly formatted.
*
*/
public class UploadReferenceTablesAction {
/**
* Regex pattern to match the header format of a CDC health stats csv. Checks that header contains
* at least sex, age, L, M, and S fields
*/
private static final String headerFormat = "Sex,Agemos,L,M,S.*";
/**
* Regex pattern to match each row of data in a CDC health stats csv. Checks that header contains at
* least sex, age, L, M, and S fields
*/
private static final String statsDataFormat = "\\d,\\d+\\.?\\d?(,-?\\d+\\.\\d+){3}(,-?\\d+\\.\\d+)*";
private CDCWeightStatsDAO weightStatsDAO;
private CDCHeightStatsDAO heightStatsDAO;
private CDCHeadCircStatsDAO headCircStatsDAO;
private CDCBmiStatsDAO bmiStatsDAO;
/**
* Constructor for UploadReferenceTablesAction. Reads in DAOFactory and initializes
* CDCStatsDAO fields with the factory.
* @param factory the DAOfactory to use for database transactions
*/
public UploadReferenceTablesAction(DAOFactory factory) {
weightStatsDAO = new CDCWeightStatsDAO(factory);
heightStatsDAO = new CDCHeightStatsDAO(factory);
headCircStatsDAO = new CDCHeadCircStatsDAO(factory);
bmiStatsDAO = new CDCBmiStatsDAO(factory);
}
/**
* Parses a CSV file and stores the statistics for average patient weights
* @param weightCSV InputStream object with weight statistics csv file
* @return true if data is stored correctly in the database.
* false if csv file is of the incorrect format and cannot be stored
*/
public boolean storeWeightStats(InputStream weightCSV) {
return storeCDCStats(weightCSV, weightStatsDAO);
}
/**
* Parses a CSV file and stores the statistics for average patient heights/lengths
* @param heightCSV InputStream object with height statistics csv file
* @return true if data is stored correctly in the database.
* false if csv file is of the incorrect format and cannot be stored
*/
public boolean storeHeightStats(InputStream heightCSV) {
return storeCDCStats(heightCSV, heightStatsDAO);
}
/**
* Parses a CSV file and stores the statistics for average patient head circumferences
* @param @param headCircCSV InputStream object with head circumference statistics csv file
* @return true if data is stored correctly in the database.
* false if csv file is of the incorrect format and cannot be stored
*/
public boolean storeHeadCircStats(InputStream headCircCSV) {
return storeCDCStats(headCircCSV, headCircStatsDAO);
}
/**
* Parses a CSV file and stores the statistics for average patient BMIs
* @param bmiCSV InputStream object with bmi statistics csv file
* @return true if data is stored correctly in the database.
* false if csv file is of the incorrect format and cannot be stored
*/
public boolean storeBMIStats(InputStream bmiCSV) {
return storeCDCStats(bmiCSV, bmiStatsDAO);
}
/**
* Parses a csv file and sends it to the CDCStatsDAO that is passed in to store the data.
* First verifies whether the csv file is formatted correctly. If the file is of the correct
* format then the file is parsed and passed into the specified CDCStatsDAO for storing.
* @param healthStatsCSV InputStream with the csv file containing the health statistics to
* store in the database
* @param dao the CDCStatsDAO to use to store the data from the csv file
* @return true if data is stored correctly in the database.
* false if csv file is of the incorrect format and cannot be stored
*/
@SuppressWarnings("resource")
private boolean storeCDCStats(InputStream healthStatsCSV, CDCStatsDAO dao) {
BufferedInputStream csvFile = new BufferedInputStream(healthStatsCSV);
try {
csvFile.mark(csvFile.available() + 1);
//If the csv file cannot be verified, close the InputStream and return false
if (!verifyCDCStatsCSV(csvFile)) {
csvFile.close();
return false;
}
csvFile.reset();
} catch (IOException e) {
return false;
}
//Create scanner to read each line of data in the csv
Scanner csvScanner = new Scanner(csvFile, "UTF-8");
//Scanner to parse through each row of data
Scanner rowScanner = null;
//String for saving a row of data
String row = "";
//Scan and throw away the header line.
csvScanner.nextLine();
//CDCStatsBean for storing health metric statistics taken from the csv file
CDCStatsBean statsBean = null;
try {
while (csvScanner.hasNextLine()) {
//Create new CDCStatsBean for storing a new row of data
statsBean = new CDCStatsBean();
//Read a row of data
row = csvScanner.nextLine();
//Read the next row if row is a header
if (row.matches(headerFormat))
continue;
//Create scanner to parse each row by using commas as the delimiter
rowScanner = new Scanner(row).useDelimiter(",");
//Get the sex field
statsBean.setSex(rowScanner.nextInt());
//Get the age field
statsBean.setAge(rowScanner.nextFloat());
//Get the L field
statsBean.setL(rowScanner.nextDouble());
//Get the M field
statsBean.setM(rowScanner.nextDouble());
//Get the S field
statsBean.setS(rowScanner.nextDouble());
//Insert CDCStatsBean into the database
dao.storeStats(statsBean);
}
} catch (DBException e) {
//If there is a DBException close the InputStream and
//return false since not all the data has been added correctly
try {
healthStatsCSV.close();
} catch (IOException e1) {
//Still return false if I/O error occurs
}
return false;
}
return true;
}
/**
* Verifies that a health stats csv file is of the correct format. Checks that the header is formatted
* correctly, and then checks that each data row contains only integers, doubles, and commas
* @param healthStatsCSV InputStream with the csv file whose format needs to be checked
* @return true if the csv file is correctly formatted. false otherwise.
*/
@SuppressWarnings("resource")
private boolean verifyCDCStatsCSV(InputStream healthStatsCSV) {
//Create scanner to read each line of data in the csv
Scanner csvScanner = new Scanner(healthStatsCSV, "UTF-8");
//String for holding a line of data from the CSV file
String line = "";
//Read the header line
if (csvScanner.hasNextLine()) {
line = csvScanner.nextLine();
} else {
csvScanner.close();
//If the csv file does not contain a line, the csv file is incorrect
return false;
}
//If the header line is incorrectly formatted then the csv file is incorrect
if (!line.matches(headerFormat)) {
csvScanner.close();
return false;
}
//Verify that each consecutive line follows correct formatting
while (csvScanner.hasNextLine()) {
line = csvScanner.nextLine();
//If none of the lines match a data line format nor a header line
//format then the csv file is incorrect
if (!line.matches(statsDataFormat) && !line.matches(headerFormat)) {
csvScanner.close();
return false;
}
}
//The csv file passes the verification process it is deemed correct
return true;
}
}