I have implemented a program to extract a log file which contains a header line, followed by zero or more data lines, in comma-separated value format. The file consists of 3 columns. The first column is the Unix time stamp, the second column is the country code, and the third column is the time in milliseconds. The data lines are not guaranteed to be in any particular order.
There are three types of sample log files:
- Empty file
- Single lined file (file containing a header line and one data line)
- Multi lined file (file containing a header line and multi data lines)
The code must work for all three input log file types.
Sample file:
TIMESTAMP,COUNTRY_CODE,RESPONSE_TIME
1511190458,US,500
1756118933,GB,137
DataFiltererTest.java
public class DataFiltererTest {
@Test
public void shouldReturnEmptyCollection_WhenLogFileIsEmpty() throws FileNotFoundException {
assertTrue(DataFilterer.filterByCountry(openFile("src/test/resources/empty"), "GB").isEmpty());
}
@Test
public void shouldReturnfilteredrows_ByCountry_WhenLogFileIsMultiLines() throws FileNotFoundException {
String[] myArray = { "1433190845", "US", "539", "1433666287", "US", "789", "1432484176", "US", "850" };
Collection<?> expected = new ArrayList<String>(Arrays.asList(myArray));
assertEquals(expected, DataFilterer.filterByCountry(openFile("src/test/resources/multi-lines"), "US"));
}
@Test
public void shouldReturnfilteredrows_ByCountry_WhenLogFileIsSingleLine() throws FileNotFoundException {
String[] myArray = { "1431592497", "GB", "200" };
Collection<?> expected = new ArrayList<String>(Arrays.asList(myArray));
assertEquals(expected, DataFilterer.filterByCountry(openFile("src/test/resources/single-line"), "GB"));
}
@Test
public void shouldReturnEmptyCollection_ByCountry_WhenLogFileIsSingleLine() throws FileNotFoundException {
assertTrue(DataFilterer.filterByCountry(openFile("src/test/resources/single-line"), "US").isEmpty());
}
@Test
public void shouldReturnEmptyCollection_ByCountryWithResponseTimeAboveLimit_WhenLogFileIsEmpty()
throws FileNotFoundException {
assertTrue(DataFilterer
.filterByCountryWithResponseTimeAboveLimit(openFile("src/test/resources/empty"), "GB", 10).isEmpty());
}
@Test
public void shouldReturnFilteredRows_ByCountryWithResponseTimeAboveLimit_WhenLogFileIsMultiLines()
throws FileNotFoundException {
String[] myArray = { "1433666287", "US", "789", "1432484176", "US", "850" };
Collection<?> expected = new ArrayList<String>(Arrays.asList(myArray));
assertEquals(expected, DataFilterer
.filterByCountryWithResponseTimeAboveLimit(openFile("src/test/resources/multi-lines"), "US", 550));
}
@Test
public void shouldReturnFilteredRows_ByCountryWithResponseTimeAboveLimit_WhenLogFileIsSingleLine()
throws FileNotFoundException {
String[] myArray = { "1431592497", "GB", "200" };
Collection<?> expected = new ArrayList<String>(Arrays.asList(myArray));
assertEquals(expected, DataFilterer
.filterByCountryWithResponseTimeAboveLimit(openFile("src/test/resources/single-line"), "GB", 150));
}
@Test
public void shouldReturnEmptyCollection_ByCountryWithResponseTimeAboveLimit_WhenLogFileIsSingleLine()
throws FileNotFoundException {
assertTrue(DataFilterer
.filterByCountryWithResponseTimeAboveLimit(openFile("src/test/resources/single-line"), "GB", 200)
.isEmpty());
}
@Test
public void shouldReturnEmptyCollection_ByCountryWithResponseTimeAboveAverage_WhenLogFileIsEmpty()
throws FileNotFoundException {
assertTrue(DataFilterer.filterByResponseTimeAboveAverage(openFile("src/test/resources/empty")).isEmpty());
}
@Test
public void shouldReturnFilteredRows_ByCountryWithResponseTimeAboveAverage_WhenLogFileIsMultiLines()
throws FileNotFoundException {
String[] myArray = { "1433190845", "US", "539", "1433666287", "US", "789", "1432484176", "US", "850" };
Collection<?> expected = new ArrayList<String>(Arrays.asList(myArray));
double average = getAverageForFilter("src/test/resources/multi-lines");
DataFilterer.setAverage(average);
assertEquals(expected,
DataFilterer.filterByResponseTimeAboveAverage(openFile("src/test/resources/multi-lines")));
}
@Test
public void shouldReturnEmptyCollection_ByCountryWithResponseTimeAboveAverage_WhenLogFileIsSingleLine()
throws FileNotFoundException {
double average = getAverageForFilter("src/test/resources/single-line");
DataFilterer.setAverage(average);
assertTrue(DataFilterer.filterByResponseTimeAboveAverage(openFile("src/test/resources/single-line")).isEmpty());
}
private double getAverageForFilter(String filename) throws FileNotFoundException {
return new Average().findAverage(openFile(filename));
}
private FileReader openFile(String filename) throws FileNotFoundException {
return new FileReader(new File(filename));
}
}
DataFilterer.java
public class DataFilterer {
private static double average;
// Method to set the average value of RESPONSETIME
public static void setAverage(double avg) {
average = avg;
}
// Method to get the average value of RESPONSETIME
public static double getAverage() {
return average;
}
public static Collection<?> filterByCountry(Reader source, String country) {
BufferedReader br = new BufferedReader(source);
String line = null;
Collection<String> additionalList = new ArrayList<String>();
int iteration = 0;
try {
while ((line = br.readLine()) != null) {
// Logic to remove header from the input data.
if (iteration == 0) {
iteration++;
continue;
}
String[] myArray = line.split(",");
List<String> myList = new ArrayList<String>(Arrays.asList(myArray));
if (myList.contains(country)) {
additionalList.addAll(myList);
}
else
{
return Collections.emptyList();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return additionalList;
}
public static Collection<?> filterByCountryWithResponseTimeAboveLimit(Reader source, String country, long limit) {
BufferedReader br = new BufferedReader(source);
String line = null;
Collection<String> additionalList = new ArrayList<String>();
int iteration = 0;
long count = 0;
long responseTime = 0;
try {
while ((line = br.readLine()) != null) {
// Logic to remove header from the input data
if (iteration == 0) {
iteration++;
continue;
}
String[] myArray = line.split(",");
List<String> myList = new ArrayList<String>(Arrays.asList(myArray));
for (String eachval : myArray) {
// Finding the RESPONSE TIME from the input line
boolean isNumeric = eachval.chars().allMatch(x -> Character.isDigit(x));
if (isNumeric) {
count = eachval.chars().count();
// Identifying between RESPONSETIME and
// REQUEST_TIMESTAMP.Unix Timestamp will be always 10
// digits or 13 digits
if (count < 10) {
responseTime = Integer.parseInt(eachval);
if (myList.contains(country)) {
if (responseTime > limit) {
additionalList.addAll(myList);
}
}
else
{
return Collections.emptyList();
}
}
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return additionalList;
}
public static Collection<?> filterByResponseTimeAboveAverage(Reader source) {
BufferedReader br = new BufferedReader(source);
String line = null;
double average = 0.0;
Collection<String> additionalList = new ArrayList<String>();
average = getAverage();
long responseTime = 0;
int iteration = 0;
long count = 0;
String[] myArray = null;
try {
while ((line = br.readLine()) != null) {
// Logic to remove header from the input data.
if (iteration == 0) {
iteration++;
continue;
}
myArray = line.split(",");
List<String> myList = new ArrayList<String>(Arrays.asList(myArray));
for (String eachval : myArray) {
// Finding the RESPONSE TIME from the input line
boolean isNumeric = eachval.chars().allMatch(x -> Character.isDigit(x));
if (isNumeric) {
count = eachval.chars().count();
// Identifying between RESPONSETIME and
// REQUEST_TIMESTAMP.Unix Timestamp will be always 10
// digits or 13 digits
if (count < 10) {
responseTime = Integer.parseInt(eachval);
if (responseTime > average) {
additionalList.addAll(myList);
}
else
{
return Collections.emptyList();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return additionalList;
}
}
Average.java
//This class is to find average of RESPONSETIME Field of input file
public class Average {
// Method to calculate the average of RESPONSETIME
public double findAverage(Reader source) {
BufferedReader br = new BufferedReader(source);
String line = null;
int iteration = 0;
String[] myArray;
Collection<Long> responseTimeList = new ArrayList<Long>();
long responseTime = 0;
long count = 0;
double average = 0.0;
try {
while ((line = br.readLine()) != null) {
// Logic to remove header from the input file
if (iteration == 0) {
iteration++;
continue;
}
myArray = line.split(",");
for (String eachval : myArray) {
// Finding the RESPONSE TIME field from the input line
boolean isNumeric = eachval.chars().allMatch(x -> Character.isDigit(x));
if (isNumeric) {
count = eachval.chars().count();
// Identifying between RESPONSETIME and
// REQUEST_TIMESTAMP. Unix Timestamp will be always 10
// digits or 13 digits
if (count < 10) {
responseTime = Integer.parseInt(eachval);
responseTimeList.add(responseTime);
}
}
}
}
// Calculating the average
average = responseTimeList.stream().mapToInt(Long::intValue).average().getAsDouble();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return average;
}
}
The code works as expected for all the input file types. Please suggest improvements for this code. Also, please check and suggest whether I need to write this many number of test cases in TDD methodology.