I have a service that converts a xls file into html. It is working just fine, but it is quite a big method that doesn't follow any SOLID principles. Therefore I would like to improve it to follow at least the Single Responsibility Principle. But I really don't know how to apply it and find the level of abstraction in my case.
@Service
public class xlsToHtmlImpl implements MultipartFileToHtmlService {
private final HtmlLayout htmlLayout;
@Autowired
public xlsToHtmlImpl(HtmlLayout htmlLayout) {
this.htmlLayout = htmlLayout;
}
@Override
public InputStream multipartFileToHtml(MultipartFile multipartFile, boolean hasOnlyOneSheet, boolean hasBorders) throws IOException {
String fileName = multipartFile.getOriginalFilename();
BufferedInputStream inputStream = new BufferedInputStream(multipartFile.getInputStream());
Workbook workbook;
assert fileName != null;
//Selecting workbook depending on FileType
if (fileName.toLowerCase().endsWith(htmlLayout.FILE_TYPES[0])) {
workbook = new HSSFWorkbook(inputStream);
} else {
workbook = new XSSFWorkbook(inputStream);
}
//Writing content of multipartFile to outputstream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(htmlLayout.openStyle());
//Selecting style to apply depending on user input
if (hasBorders) {
outputStream.write(htmlLayout.noBordersStyle());
} else {
outputStream.write(htmlLayout.withBordersStyle());
}
outputStream.write(htmlLayout.closeStyle());
outputStream.write(htmlLayout.openNewHtml());
outputStream.write(fileName.getBytes());
//Different algorithm for the content of the body depending on user input
Sheet sheet;
if (hasOnlyOneSheet) {
sheet = workbook.getSheetAt(0);
Iterator<Row> rows = sheet.rowIterator();
while (rows.hasNext()) {
Row row = rows.next();
Iterator<Cell> cells = row.cellIterator();
outputStream.write(htmlLayout.newLine());
outputStream.write(htmlLayout.newRow());
while (cells.hasNext()) {
Cell cell = cells.next();
outputStream.write(htmlLayout.newCell());
outputStream.write(cell.toString().getBytes());
outputStream.write(htmlLayout.closeCell());
}
outputStream.write(htmlLayout.closeRow());
}
} else {
for (int i = 0; i< workbook.getNumberOfSheets(); i++) {
sheet = workbook.getSheetAt(i);
Iterator<Row> rows = sheet.rowIterator();
outputStream.write(htmlLayout.newLine());
outputStream.write(htmlLayout.newRow());
outputStream.write(htmlLayout.closeCell());
outputStream.write(htmlLayout.closeRow());
outputStream.write(htmlLayout.newLine());
while (rows.hasNext()) {
Row row = rows.next();
Iterator<Cell> cells = row.cellIterator();
outputStream.write(htmlLayout.newLine());
outputStream.write(htmlLayout.newRow());
while (cells.hasNext()) {
Cell cell = cells.next();
outputStream.write(htmlLayout.newCell());
outputStream.write(cell.toString().getBytes());
outputStream.write(htmlLayout.closeCell());
}
outputStream.write(htmlLayout.closeRow());
}
}
}
outputStream.write(htmlLayout.newLine());
outputStream.write(htmlLayout.closeHtml());
outputStream.close();
//Returning result as ByteArrayInputStream to controller
return new ByteArrayInputStream(outputStream.toByteArray());
}
Where htmlLayout
contains html snippet like:
public byte[] closeHtml() {return "</table></body></html>".getBytes();}
I tried to follow this article: https://www.baeldung.com/java-single-responsibility-principle#:~:text=As%20the%20name%20suggests%2C%20this,only%20one%20reason%20to%20change.&text=These%20classes%20are%20harder%20to%20maintain.
Following this article, I tried to create different classes as follow:
public class HtmlStyleWrapper {
private byte[] style;
public byte[] withBordersStyle() {
return ("table, td{" +
" border: 1px solid black;\n" +
" border-collapse: collapse;\n" +
" padding: 9px;\n" +
"}").getBytes();
}
public byte[] noBordersStyle() {
return ("td {" +
" padding: 9px;\n" +
"}").getBytes();
}
public byte[] openStyle() {
return "</title></head><body><style>".getBytes();
}
public byte[] closeStyle() {
return "</style><table>".getBytes();
}
public void wrapStyle(ByteArrayOutputStream outputStream, boolean hasBorders) throws IOException {
outputStream.write(openStyle());
if (hasBorders) {
outputStream.write(noBordersStyle());
} else {
outputStream.write(withBordersStyle());
}
outputStream.write(closeStyle());
}
public class HtmlBodyWrapper {
private byte[] body;
public byte[] openNewHtml() {
return "<!DOCTYPE html><html><head><title>".getBytes();
}
public byte[] newLine() {
return "\n".getBytes();
}
public byte[] closeHtml() {
return "</table></body></html>".getBytes();
}
public byte[] newRow() {
return "<tr>".getBytes();
}
public byte[] closeRow() {
return "</tr>".getBytes();
}
public byte[] newCell() {
return "<td>".getBytes();
}
public byte[] closeCell() {
return "</td>".getBytes();
}
public void wrapBody(ByteArrayOutputStream outputStream, String fileName, boolean hasOnlyOneSheet, Workbook workbook) throws IOException {
//Write to outputstream
}
The aim would be to get something like
wrapHTMLBody(wrapStyle(htmlLayout.getHTML_STYLE()), table)
But I feel like I'm not taking the right approach and that I didn't understand correctly SRP.
Aucun commentaire:
Enregistrer un commentaire