I have an application which has to handle multiple types of documents.
I have a service generateReport(DocumentEntity) which has to build a report, this service will be called for every types of child of DocumentEntity.
The thing is that the report we want to build depends on the type of document.
My code bellow works but I feel like there is a better way to do it :
Lets say we have DocumentDonationEntity & DocumentBookEntity which extends DocumentEntity :
public abstract class DocumentEntity {
protected Long id;
protected String name;
// getters & setters
}
public class DocumentDonationEntity extends DocumentEntity {
private String donatorName;
// getters & setters
}
public class DocumentBookEntity extends DocumentEntity {
private Long price;
// getters & setters
}
And ReportDataBook & and ReportDataDonation which extends ReportData :
public abstract class ReportData {
protected Long id;
protected String name;
public void checkNotNull() throws MyException {
if this.id == null
throw new myException();
if this.name == null
throw new myException();
// other generic stuff
}
// getters & setters
}
public class ReportDataBook extends ReportData {
private String price;
public void checkNotNull() throws MyException {
super.checkNotNull();
if this.price == null
throw new myException();
// other stuff specific to books
}
// getters & setters
}
public class ReportDataDonation extends ReportData {
private String donatorName;
public void checkNotNull() throws MyException {
super.checkNotNull();
if this.donatorName == null
throw new MyException();
// other stuff specific to donations
}
// getters & setters
}
Plus an utils class :
public class Utils {
public ReportData fillReport(DocumentEntity document) throws Exception {
if (document instanceof DocumentBookEntity) {
ReportDataBook data = new ReportDataBook();
completeReportData(data, (DocumentBookEntity) document);
completeReportData(data, document);
return data;
} else if (document instanceof DocumentDonationEntity) {
ReportDataDonation data = new ReportDataDonation ();
completeReportData(data, (DocumentDonationEntity) document);
completeReportData(data, document);
return data;
}
return null;
}
public void completeReportData(ReportData data, DocumentEntity document) {
// some generic stuff
}
public void completeReportData(ReportDataBook data, DocumentBookEntity document) {
// some stuff specific to books
}
public void completeReportData(ReportDataDonation data, DocumentDonationEntity document) {
// some stuff specific to donations
}
}
Then I have a Service :
@Service
public class MyService implements IMyService {
@Override
public boolean generateReport(DocumentEntity document) throws MyException {
ReportData data = initializeReport(document);
// do some other stuff
}
private ReportData initializeReport(DocumentEntity document) throws myException {
if (document instanceof DocumentBookEntity) {
ReportDataBook data = (ReportDataBook) utils.fillReport(document);
data.checkNotNull();
return data;
} else if (document instanceof DocumentDonationEntity) {
ReportDataDonation data = (ReportDataBook) utils.fillReport(document);
data.checkNotNull();
return data;
}
return null;
}
}