Generic getter in container object - java

Some container class holds list of objects of base class "Table" (like WoodenTable, MetalTable...). Each Table class keeps its MaterialType (MaterialType.Wood, MaterialType.Metal...). Question is how to provide proper getter method for container class that could return each SubClass of Table.
So far I've found following ways:
1.Getter with material type as parameter. Danger here is ClassCastException if type of T doesn't correspond to materialType:
<T extends Table> T getTable(MaterialType materialtype)
WoodenTable table = getTable(MaterialType.Wood);
MetalTable table = getTable(MaterialType.Wood); // ups... exception
2.Getter with Class parameter. Safe but not so clear for user (comparing to MaterialType as parameter):
<T extends Table> T getTable(Class<T> tableClass)
WoodenTable table = getTable(WoodenTable.class);
3.Getter for each Table SubClass. Cumbersome to use,write and add new Table subClasses:
WoodenTable getWoodenTable()
WoodenTable table = getWoodenTable();
4.Getter for just Table interface. Cast done outside of container class if necessary.
Table getTable(MaterialType materialType)
WoodenTable woodenTable = (WoodenTable)getTable(MaterialType.Wood)
Is any other (better) way to do that? If not, then which of those would be most appriopriate or least smelly?

It should be just this simple:
public Table getTable()
{
return this.table;
}
This will return a Table object it is up to the invoker to do with it what they want. Similar to the following block:
public Collection<String> getCollection()
{
return new ArrayList<String>();
}
The body returns an ArrayList but the function really returns a Collection. A well defined API that utilizes the most common interface between objects will give you this same flexibility.
EDIT
Yes, that could be one use case but quite often I need also something
like : for(Table t : TableContainer) {
(SubClassA)t.doSomethingSpecificForA();} and that's were my problems
begin.
Let us assume the following interface and implementations:
public interface Table
{
Table getTable();
void doSpecial();
}
public class WoddenTable implements Table
{
...
public Table getTable()
{
return this;
}
public void doSpecial()
{
mySpecial();
}
private void mySpecial()
{
System.out.println("Wooden");
}
}
public class MetalTable implements Table
{
...
public Table getTable()
{
return this;
}
public void doSpecial()
{
mySpecial();
}
private void mySpecial()
{
System.out.println("Metal");
}
}
and the following code:
public static void main(String[] args)
{
Collection<Table> tables = new ArrayList<Table>();
tables.add(new WoodenTable());
tables.add(new MetalTable());
for(Table table : tables)
{
table.doSpecial();
}
}
The approach here is that there is a shared public API. And the internals of each class are not exposed so the need to do something special for each class is hidden behind the common interface. This prevents having to do instance of checks or any of the other messy ways to solve this type of problem.

I would recommend to stop thinking about tables as about data structures with attributes (material), and start treating them as "persons" (Object Thinking). Don't get a "material" out of them. Instead, let them expose their behavior.
When you change the design of the table you will automatically change the design of their container. And it will become obvious that the container shouldn't care about tables' materials, but should let them control whether they want to get out of container or remain there.

Related

Java class method with Class and Field as parameters

How can i create a method that accepts Class and Field as parameters? Like this:
List<SomeClassEntity> list = ...;
// Service to make useful things around a list of objects
UsefulThingsService<SomeClassEntity> usefulThingsService = new UsefulThingsService<>();
// Maybe invoke like this. Did't work
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, SomeClassEntity::getFieldOne);
// or like this. Will cause delayed runtime erros
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, "fieldTwo");
public class SomeClassEntity {
Integer fieldOne = 10;
Double fieldThree = 0.123;
public Integer getFieldOne() {
return fieldOne;
}
public void setFieldOne(Integer fieldOne) {
this.fieldOne = fieldOne;
}
public Double getFieldThree() {
return fieldThree;
}
public void setFieldThree(Double fieldThree) {
this.fieldThree = fieldThree;
}
}
public class UsefulThingsService<T> {
public void makeUsefulThings(Class<T> someClassBClass, String fieldName) {
// there is some code
}
}
Want to have correct references on compile stage, not at runtime.
Update:
I need code that would look more convenient than this:
Field fieldOne = null;
try {
fieldOne = SomeClassEntity.class.getDeclaredField("fieldOne");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
usefulThingsService.makeUsefulThings(SomeClassEntity.class, fieldOne);
I apologize for the next clarification.
Update 2:
- The service compares the list with the previous list, reveals only the changed fields of objects (list items) and updates these fields in the objects in the original list.
- Currently i use annotation on entity's field that is actually ID of the entity and that ID is used to detect identically entities (old and new) when i need to update field of entity in source list.
- Service detect annotated field and use it for next update process.
- I want to refuse to use annotations and provide an Field directly in constructor of service. Or use something other that could establish a relationship between class and field on compilation stage.
Assuming that you want field access because you want to get and set the value, you’d need two functions:
public class UsefulThingsService<T> {
public <V> void makeUsefulThings(List<T> list, Function<T,V> get, BiConsumer<T,V> set) {
for(T object: list) {
V v = get.apply(object);
// there is some code
set.accept(object, v);
}
}
}
and
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldOne, SomeClassEntity::setFieldOne);
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldThree, SomeClassEntity::setFieldThree);
There are, however, some things open. E.g., how is this service supposed to do something useful with the field resp. property, without even knowing its actual type. In your example, both are subtypes of Number, so you could declare <V extends Number>, so the method knows how to extract numerical values, however, constructing an appropriate result object would require specifying another function argument.

OO design - is this design flawed?

I am creating a logic for web application to managing consents from user.
The model class that is persisted in the DB will have multiple fields, from which only a set will be changed with user request. E. g. class will have 10 fields with various consents, but user will be willing to change only 2 of those. To avoid writing a big chain of if-else's I designed this classes, to harness polymorphism to do the job for me, but somehow this design seems flawed to me. Could you tell me if this is proper way to do it?
PROBLEM: Change values of only subset of fields from large set of fields in class.
For sake of simplicity I removed getter/setters methods and some fields.
Main logic for changing consents:
public class GdprServiceImpl implements GdprService {
private final ConsentRepository consentRepository;
#Autowired
public GdprServiceImpl(ConsentRepository consentRepository) {
this.consentRepository = consentRepository;
}
#Override
public void changeConsent(User user, List<ConsentDto> consents) {
Optional<Consent> optionalConsent = consentRepository.findByUser(user);
if(optionalConsent.isPresent()) {
Consent consent = optionalConsent.get();
for(ConsentDto consentDto : consents) {
consentDto.apply(consent);
}
consentRepository.save(consent);
}
else {
Consent consent = new Consent();
consent.setUser(user);
for(ConsentDto consentDto : consents) {
consentDto.apply(consent);
}
consentRepository.save(consent);
}
}
Model class:
public class Consent {
private Boolean messageConsent;
private Boolean recordConsent;
/*CONSTRUCTOR, OTHER METHODS AND FIELDS OMITTED*/
}
Classes that will change a set of fields from Consent class:
public abstract class ConsentDto {
public abstract void apply(Consent consent);
}
public class RecordConsentDto extends ConsentDto {
private boolean consentValue;
public RecordConsentDto(boolean consentValue) {
this.consentValue = consentValue;
}
#Override
public void apply(Consent consent) {
consent.setRecordConsent(consentValue);
}
}
public class MessageConsentDto extends ConsentDto {
private boolean consentValue;
public MessageConsentDto(boolean consentValue) {
this.consentValue = consentValue;
}
#Override
public void apply(Consent consent) {
consent.setMessageConsent(this.consentValue);
}
}
You are right about the design having a "smell".
This is because the DB design is not normalized.
having a list of consents in one record is an indication. while technically it is allowed, classic RDBMS design dictatets that arrays should be represented as either one-to-many or many-to-many relation between tables. Of course, same in the object model.
a Fully normalized solution will have a consent_catalog table and many-to-many relation to users:
table consent_catalog {
int id // PK
String name
}
The catalog acts as "consent enum", having one row per type of consent (record, message, etc)
table user_consents {
int user_id references users(id)
int consent_id references consent_catalog(id)
}
This table has rows only for consents accepted by the user. no "false" consents. This design opens up new possibilities like knowing which users have a specific consent or mulitple consents in common.
This design feels like an overkill. At the end of the day you are always calling consent.setMessageConsent() or similar it's wrapped with an enum field and a class implementing ConsumerDto (which is really a Consumer). Generally DTO are not supposed to implement business logic yet one could argue that apply method is one.
It really would be cleaner to have UserConsent POJO with Boolean fields. The exception would be if triggering one consent should trigger other but it's not clear from your example.
Just my two cents. I'd prefer to see either an anemic POJO passed around or DDD aggregate root for user that manages consents but not something in between.

jooq - Add code to the generated Record class

I learning how to work with jooq. I would like to know if I can add some domain-level methods in to the generated Record classes.
Suppose the record was this:
public class ConCalCompanyRecord extends org.jooq.impl.UpdatableRecordImpl<com.aesthete.csmart.connect.model.db.gen.tables.records.ConCalCompanyRecord> implements org.jooq.Record6<java.lang.Integer, java.lang.Integer, java.lang.String, java.lang.String, java.sql.Timestamp, java.sql.Timestamp> {
// properties
// getters and setters
// I would like to add a method like this:
public void isABlueCompany(){
// work with the fields
}
}
But I know if I do this, as soon as I generate this class again from the DB, all my changes will get lost. So what is the recommended way of doing this?
A wrapper class? A sub class to the record? If its any of these, how do I get jooq to recognise these classes at the time of fetching. For example:
connectionFacade.getDSLContext()
.selectFrom(CON_CAL_INSTANCE)
.where(CON_CAL_INSTANCE.DATE.between(
new Date(datesOfTheWeekForDate[0].toDate().getTime()), new Date(datesOfTheWeekForDate[1].toDate().getTime())))
.orderBy(CON_CAL_INSTANCE.DATE)
.fetch()
.into(new RecordHandler<ConCalInstanceRecord>() {
#Override
public void next(ConCalInstanceRecord record) {
calendarEntries.addToList(new com.aesthete.csmart.connect.model.domain.records.ConCalInstance(record));
}
});
In the above case I am providing a wrapper called ConCalInstance to the record class. Do I have to write a RecordHandler like this for every query I execute if I need to use a wrapper?
What is the recommended way of doing this?
You can override jOOQ's default code generator with your own extensions. This is documented here, in the manual:
http://www.jooq.org/doc/latest/manual/code-generation/codegen-custom-code/
The example shows how it works:
public class MyGenerator extends JavaGenerator {
#Override
protected void generateRecordClassFooter(
TableDefinition table,
JavaWriter out
) {
super.generateRecordClassFooter(table, out);
if ("SOME_TABLE".equals(table.getName())) {
out.println();
out.tab(1).println("public void isABlueCompany() {");
out.tab(2).println("// Your logic here");
out.tab(1).println("}");
}
else if ("SOME_OTHER_TABLE".equals(table.getName())) {
// [...]
}
}
}
Based on Lukas's suggestion I landed up adding code to my generated Record like this
public class ConCalInstanceRecord extends org.jooq.impl.UpdatableRecordImpl....{
//fields and getter and setters of the generated record..
private ConCalInstanceBehaviour behaviour;
public ConCalInstanceBehaviour getBehaviour(){
if(behaviour==null){
behaviour=new ConCalInstanceBehaviour(this);
}
return behaviour;
}
}
Sort of like the wrapper like I was talking about, but the other way around, the record wraps a behaviour class. I can now add custom behaviour into my behaviour classes without having to go back to the generator every time I needed to add a new method.
This allowed me to access additional domain behaviour like this...
record.getBehaviour().doSomething();

Understanding best use of Java Generics in this example case

Let's say I have a manufacturing scheduling system, which is made up of four parts:
There are factories that can manufacture a certain type of product and know if they are busy:
interface Factory<ProductType> {
void buildProduct(ProductType product);
boolean isBusy();
}
There is a set of different products, which (among other things) know in which factory they are built:
interface Product<ActualProductType extends Product<ActualProductType>> {
Factory<ActualProductType> getFactory();
}
Then there is an ordering system that can generate requests for products to be built:
interface OrderSystem {
Product<?> getNextProduct();
}
Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:
class Dispatcher {
Map<Factory<?>, Queue<Product<?>>> workQueues
= new HashMap<Factory<?>, Queue<Product<?>>>();
public void addNextOrder(OrderSystem orderSystem) {
Product<?> nextProduct = orderSystem.getNextProduct();
workQueues.get(nextProduct.getFactory()).add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
factory.buildProduct(workQueues.get(factory).poll());
}
}
Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)
Now the question:
The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:
The method buildProduct(capture#5-of ?) in the type Factory<capture#5-of ?> is not applicable for the arguments (Product<capture#7-of ?>)
I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...
Changing it to the following, for example, doesn't help either:
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy()) {
Product<?> product = workQueues.get(factory).poll();
product.getFactory().buildProduct(product);
}
}
Even though in this case it should be clear that this is ok...
I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.
Any ideas?
EDIT:
A quick example for an implementation of Product and Factory:
class Widget implements Product<Widget> {
public String color;
#Override
public Factory<Widget> getFactory() {
return WidgetFactory.INSTANCE;
}
}
class WidgetFactory implements Factory<Widget> {
static final INSTANCE = new WidgetFactory();
#Override
public void buildProduct(Widget product) {
// Build the widget of the given color (product.color)
}
#Override
public boolean isBusy() {
return false; // It's really quick to make this widget
}
}
Your code is weird.
Your problem is that you are passing A Product<?> to a method which expects a ProductType which is actually T.
Also I have no idea what Product is as you don't mention its definition in the OP.
You need to pass a Product<?> to work. I don't know where you will get it as I can not understand what you are trying to do with your code
Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
// factory has the type "Factory of ?"
for (Factory<?> factory: workqueues.keySet())
// the queue is of type "Queue of Product of ?"
Queue<Product<?>> q = workqueues.get(factory);
// thus you put a "Product of ?" into a method that expects a "?"
// the compiler can't do anything with that.
factory.buildProduct(q.poll());
}
Got it! Thanks to meriton who answered this version of the question:
How to replace run-time instanceof check with compile-time generics validation
I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):
Be more specific about the OrderSystem:
interface OrderSystem {
<ProductType extends Product<ProductType>> ProductType getNextProduct();
}
Define my own, more strongly typed queue to hold the products:
#SuppressWarnings("serial")
class MyQueue<T extends Product<T>> extends LinkedList<T> {};
And finally, changing the Dispatcher to this beast:
class Dispatcher {
Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
#SuppressWarnings("unchecked")
public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
ProductType nextProduct = orderSystem.getNextProduct();
MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
myQueue.add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
buildProduct(workQueues.get(factory).poll());
}
public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
product.getFactory().buildProduct(product);
}
}
Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.
Also note, that the #SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)

Looking for a good pattern to implement View adapters for objects, in Java/JSP

this is more a design question. Suppose you have many beans A, B, C.... Then you have a class that creates, say, tables out of beans. You need something that tells this class which properties of those beans to display, what names give to the columns and other rendering properties. I don't want to hardwire this in the class for each bean class, so I was thinking of giving the beans a common interface like TableAdapterProvider, that would come out with a class that gives all instructions to the rendering class. The problem is that I can't make an interface method static in Java. And this doesn't seem very clean for a number of reasons... for example to create an empty table I have to allocate a bean and then call the interface method TableAdapterProvider to retrieve the "rendering" class.
I thought of creating a factory like TableAdapterFactory(Class beanClass) that returns the correct TableAdapter for each bean class without instanting any. Anyway I have to update this factory for every bean I create.
Another solution could be use special naming conventions, for example if a bean name is Apple, then AppleTableRenderer will be the renderer. I can scan a package in search of this when the TableRenderer starts so the associations are done automatically.
Do you know of a better pattern? What do you think of my approaches?
For the future, is there a good book with recipes like these to use in web apps?
Seems to me that any bean (A, B, C..) that needs to be displayed as a HTML table (by some kind of TableRenderer) should implement an interface that provides the renderer with the required information. The likely interface methods would get the columns headers and the table data. Maybe also one for table style, but that is a bit subjective.
With this in mind you might have;
public interface Renderable
{
public List<String> getHeaders();
public List<List<String>> getData();
}
public class A implements Renderable
{
private String name;
private int age;
public List<String> getHeaders()
{
List<String> headers = new ArrayList<String>();
headers.add("Name");
headers.add("Age");
return list;
}
public List<List<String>> getData()
{
List<List<String>> data = new ArrayList<List<String>();
List<String> row = new ArrayList<String>();
row.add(name);
row.add(String.valueOf(age));
data.add(row);
return data;
}
//getters and setters
}
It's then pretty trivial to write your TableRenderer;
public class TableRenderer
{
public String render(Renderable r)
{
//draw a HTML table
//draw table headers from r.getHeaders()
//draw table rows from r.getData()
}
}
Note that instead of writing a TableRenderer class you might want to use the JSTL <c:forEach> syntax, which is a more standard approach.
Maybe a combination. Keep the factory, that's a good pattern for your task: a factory that creates the correct renderer for a given bean.
But let the factory try to find the renderer - either by scanning a certain package or by reading the renderer classname from a configuration file.
And if the factory can't find a renderer, it could use a default renderer that simply reflects the bean class and creates cells for all fields.
you could use an abstract class.
implement chosen common methods in the abstract class
implement class specific method within each class.
added code.
to generate the table you need to call generateTable method with the paremeter generated by the processBean methhod
public abstract class Parent {
/**
* This method generates table from common input
* #param commonTableMaterial
* #return
*/
private String generateTable(String commonTableMaterial ){
return commonTableMaterial+"table me";
}
/**
* This method is class specific - generating needed input to table
* #return
*/
abstract protected String processBean() ;
}
public class ChildA extends Parent {
private String firstName ;
private String lastName ;
private String hiddenName ;
#Override
protected String processBean() {
return firstName +lastName ;
}
}

Categories

Resources