Reputation: 2606
I am building an application that is generating PDF documents for sales orders and sales invoices. For simplicity I have exluded redundant logic and fields.
Here is my class structure:
public class SalesEntity {
public String name;
public String createdDate;
}
public class SalesOrder extends SalesEntity {
}
public class SalesInvoice extends SalesEntity {
public String invoiceSpecificField;
}
and similar scturcure for wrapper and list items:
public class SalesEntityItem {
public String name;
public String price;
}
public class SalesOrderItem extends SalesEntityItem {
}
public class SalesInvoiceItem extends SalesEntityItem {
public String invoiceItemSpecificField;
}
public class SalesEntityResponse {
public SalesEntity salesEntity;
public List<SalesEntityItem> salesEntityItems;
}
and here is first part of the problem.
public class SalesOrderEntityResponse extends SalesEntityResponse {
// public SalesOrder salesEntity; <-- say somehow to java that in this subclass the property type should also be subclass
// public List<SalesOrderItem> salesEntityItems;
}
For building mechanism I am using template method:
public class PDFBuilder extends AbstractPDFBuilder {
protected void buildPdfDocument(Map<String, Object> model /*...*/) throws Exception {
/*...*/
addEntityNumber(document, salesEntityResponse);
addItems(document, salesEntityResponse);
}
}
public class OrderPDFBuilder extends PDFBuilder {
/*...*/
@Override
protected void addEntityNumber(Document document, SalesEntityResponse entityResponse) throws DocumentException {
/*...*/
PdfPTable documentNameTable = new PdfPTable(1);
Phrase documentNamePhrase = new Phrase(entityResponse.labels.account_number, timesFont);
PdfPCell documentNameCell = new PdfPCell(documentNamePhrase);
documentNameTable.addCell(documentNameCell);
document.add(documentNameTable);
}
@Override
protected void addItems(Document document, SalesEntityResponse entityResponse) throws DocumentException {
/*...*/
for (SalesEntityItem salesEntityItem : entityResponse.salesEntityItems) {
/* Items adding specific logic */
}
}
}
And if first part of somwhow solveable, here comes main part:
Question: How can I make specific template method implementations (OrderPDFBuilder, InvoicePDFBuilder
)
receive parameters of subtype SalesEntityResponse
(SalesOrderResponse
and SalesInvoiceResponse
) respectively? So that in specific implementations I can use specific fields of those entities. Does it make sense? I assume here is something related to bounded types, but I am not sure how to use it properly.
Upvotes: 0
Views: 89
Reputation: 587
As you've established generics are how you achieve this. So firstly you'll need to stick your generics decleration on the SalesEntityResponse
:
public class SalesEntityResponse<T extends SalesEntity, U extends SalesEntityItem> {
public T salesEntity;
public List<U> salesEntityItems;
}
Then in the declaration of your subtypes you tell it what concrete types they hold:
public class SalesOrderEntityResponse extends SalesEntityResponse<SalesOrder, SalesOrderItem> {
}
To make the "magic" work in your addItems
method you'll have to also have to add generics to which ever class/interface declares the addItems
method, this is presumably AbstractPDFBuilder
? So something like:
public abstract class AbstractPDFBuilder<T extends SalesEntity, U extends SalesEntityItem, V extends SalesEntityResponse<T, U>> {
protected abstract void addItems(Document document, V entityResponse) throws DocumentException;
}
}
And then your concrete PDFBuilder
types need to supply the relavant generics:
public class SalesOrderPDFBuilder extends AbstractPDFBuilder<SalesOrder, SalesOrderItem, SalesOrderEntityResponse> {
protected void addItems(Document document, SalesOrderEntityResponse entityResponse) {
}
}
Upvotes: 1