I wrote a generic data converter that takes one kind of data and converts to JSON and XML types of file. Now, it reads data from the given CSV file hotels.csv. The first line is a header which describes all field names and, follows the rules given below:
a. A hotel name may only contain UTF-8 characters.
b. The hotel URL must be valid
c. Hotel ratings are given as a number from 0 to 5 stars. There may be no negative numbers
d. the tool needs to be extensible to new data output formats
e. Write proper Unit tests where necessary
f. Options to sort/group the data before writing it
AS the project is little larger to put here entirely, I keep it in the Github and please have a look from there. I provided the structure of the project below -
Here are some classes with importance:
App.java
public class App {
public static void main(String[] args) throws Exception {
DataConverter dataConverter = new DataConverter(Constant.HOTEL_DATA);
System.out.println(new GetMessage().welcomeTrivagoDevTeam());
System.out.println();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String input = scanner.nextLine();
System.out.println("ENTER Q OR QUIT TO QUIT \n");
if (input.toLowerCase().equals("q") || input.toLowerCase().equals("quit")) {
System.out.println("SEE YOU");
System.exit(0);
}
try {
int caseValue = Constant.DESIRED_OUTPUT_FILE = Integer.parseInt(input);
switch (caseValue) {
case 1:
System.out.println("INPUT : " + input + " " + " :XML ");
System.out.println();
break;
case 2:
System.out.println("INPUT : " + input + " " + " :JSON ");
System.out.println();
break;
default:
System.out.println("OUTPUT TYPE NOT SUPPORTED ");
}
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("IF WOULD YOU LIKE TO SORT/GROUP THE RESULT, \nENTER YES OR Y");
System.out.println("OTHERWISE HIT ENTER TO CONTINUE");
input = scanner.nextLine();
if (input.isEmpty()) {
System.out.println("LETS GET THE OUTPUT FILE \n");
break;
} else if (input.toLowerCase().equals("yes") || input.toLowerCase().equals("y")) {
System.out.println("HOW WOULD YOU LIKE TO SORT THE RESULT ?");
System.out.println("ENTER 1 FOR BASED ON NAME ");
System.out.println("ENTER 2 FOR BASED ON THE HOTEL RATINGS");
input = scanner.nextLine();
if (input.toLowerCase().equals("1")) {
Constant.DESIRED_SORTING = 1;
break;
} else if (input.toLowerCase().equals("2")) {
Constant.DESIRED_SORTING = 2;
break;
} else
return;
} else
System.out.println("FOLLOW THE INSTRUCTIONS");
return;
}
dataConverter.changeDataFormat(Constant.DESIRED_OUTPUT_FILE, Constant.DESIRED_SORTING);
}
}
FileReader.java
public abstract class FileReader implements FileReadable,
XmlFileConvertable,
JsonFileConvertable {
protected List<HotelData> rows;
protected HotelData hotelData;
protected Headers headers;
private String fileName = null;
public FileReader(String fileName) {
this.fileName = fileName;
this.rows = new ArrayList<>();
this.hotelData = null;
this.headers = null;
fileReader();
}
public void fileReader() {
try {
readCsvFile();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
}
@Override
public void readCsvFile() throws FileNotFoundException {
File file = new FileFinder().getTheFile(fileName);
try (Scanner scanner = new Scanner(file)) {
List<String> line = parseLine(scanner.nextLine());
if (line != null) {
// name,address,stars,contact,phone,uri
headers = new Headers(line.get(0),
line.get(1),
line.get(2),
line.get(3),
line.get(4),
line.get(5));
}
while (scanner.hasNext()) {
line = parseLine(scanner.nextLine());
if (line != null) {
// name,address,stars,contact,phone,uri
String name = line.get(0);
String address = line.get(1);
String stars = line.get(2);
String contact = line.get(3);
String phone = line.get(4);
String uri = line.get(5);
boolean nameValidated = isNameIsUTF8(name);
boolean urlIsValidated = isUrlValidated(uri);
boolean hotelRatingValidated = isValidHotelRating(stars);
// name, uri and the hotel rating validated
if (nameValidated && urlIsValidated && hotelRatingValidated) {
hotelData = new HotelData(name, address, stars, contact, phone, uri);
rows.add(hotelData);
}
}
}
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
DataConverter.java
public class DataConverter extends FileReader {
// private StringBuilder stringBuilder;
public DataConverter(String csvFile) {
super(csvFile);
}
public void changeDataFormat(int value, int sort) {
// sorting is required by the client
if (sort != -1)
sortDataList(sort, rows);
// get the output in the desired format
switch (value) {
case 1:
dataToXmlConverter();
break;
case 2:
dataToJsonConverter();
break;
default:
System.out.println("FILE OUTPUT TYPE IS NOT SUPPORTED");
break;
}
}
@Override
public void dataToXmlConverter() {
if (rows == null || rows.isEmpty())
return;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
try {
docBuilder = docFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("info");
doc.appendChild(rootElement);
for (int i = 0; i < rows.size(); i++) {
HotelData hotelData = rows.get(i);
// name,address,stars,contact,phone,uri
Element content = doc.createElement("row");
rootElement.appendChild(content);
Attr attr = doc.createAttribute("id");
attr.setValue(String.valueOf(i + 1));
content.setAttributeNode(attr);
Element name = doc.createElement(headers.getName());
name.appendChild(doc.createTextNode(hotelData.getName()));
content.appendChild(name);
Element address = doc.createElement(headers.getAddress());
address.appendChild(doc.createTextNode(hotelData.getAddress()));
content.appendChild(address);
Element stars = doc.createElement(headers.getStars());
stars.appendChild(doc.createTextNode(hotelData.getStars()));
content.appendChild(stars);
Element contact = doc.createElement(headers.getContact());
contact.appendChild(doc.createTextNode(hotelData.getContact()));
content.appendChild(contact);
Element phone = doc.createElement(headers.getPhone());
phone.appendChild(doc.createTextNode(hotelData.getPhone()));
content.appendChild(phone);
Element uri = doc.createElement(headers.getUri());
uri.appendChild(doc.createTextNode(hotelData.getUri()));
content.appendChild(uri);
}
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(Constant.OUTPUT_LOC + "/result.xml"));
transformer.transform(source, result);
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("CONVERTED TO XML");
}
@Override
public void dataToJsonConverter() {
// long startTime = System.currentTimeMillis();
// JSON CONVERSION TIME : 144 (FOR NAME BASED GROUPING)
File file = new File(Constant.OUTPUT_LOC + "/result.json");
String jsonValue = dataToJsonConverterHelper(rows);
try (FileOutputStream fop = new FileOutputStream(file)) {
// if file doesn't exists, then create it
if (!file.exists()) {
file.createNewFile();
}
// get the content in bytes
byte[] contentInBytes = jsonValue.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
System.out.println("CONVERTED TO JSON");
}
catch (IOException e) {
e.printStackTrace();
}
// long estimatedTime = System.currentTimeMillis() - startTime;
// System.out.println("JSON CONVERSION TIME : " + estimatedTime);
}
public String dataToJsonConverterHelper(List<HotelData> rows) {
String jsonValue = "";
if (rows == null || rows.isEmpty())
return jsonValue;
jsonValue = hotelsToJSON(rows);
return jsonValue;
}
// @Override
// public void dataToJsonConverter() {
//
// ObjectMapper mapper = new ObjectMapper();
// long startTime = System.currentTimeMillis();
// JSON CONVERSION TIME : 8114 (FOR NAME BASED GROUPING)
// try {
// String jsonInString = "";
//
// for (HotelData hotels : rows) {
// jsonInString += mapper.writeValueAsString(hotels);
// }
// mapper.writeValue(new File(Constant.OUTPUT_LOC + "/result.json"), jsonInString);
// }
// long startTime = System.currentTimeMillis();
// JSON CONVERSION TIME : 332 (FOR NAME BASED GROUPING)
// better performance using the StringBuilder
// try {
// stringBuilder = new StringBuilder();
//
// for (HotelData hotels : rows) {
// stringBuilder.append(mapper.writeValueAsString(hotels).trim());
// }
// mapper.writeValue(new File(Constant.OUTPUT_LOC + "/result.json"), stringBuilder.toString());
// }
// catch (JsonGenerationException e) {
// e.printStackTrace();
// } catch (JsonMappingException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// long estimatedTime = System.currentTimeMillis() - startTime;
// System.out.println("JSON CONVERSION TIME : " + estimatedTime);
// System.out.println("CONVERTED TO JSON");
// }
}
How can I improve the architecture, elegance and performance (lesser priority in this context) of code ?
