stephenh / dtonator

code generator for creating DTOs and mapping to domain objects
Other
14 stars 5 forks source link

Generic Typed Properties #7

Open pbtura opened 7 years ago

pbtura commented 7 years ago

Is there any current support for generic typed properties?

stephenh commented 7 years ago

No. In my domain modeling so far, I've not had the need/use case for that, e.g. just objects with primitives (firstName), lists of primitives (lastNames), entity references (parentAccount), and lists of entity references (childAccounts), have been sufficient.

Open to the idea of generics if you can give a nice use case/example/etc.

pbtura commented 7 years ago

Here is an example from one of my projects where I ran into this issue. We have a library that includes domain objects that are shared across multiple projects. Each project can then extend the 'common' version of the class to add additional functionality that is project specific. In this case, I am dealing with a Brand class that has a reference to a SubCollection class. Since SubCollection could be extended in a project that uses the lib, the common version of Brand needs to be able to handle those custom subcollections. We use generics to define a type 'T' that extends the common version of SubCollection. By using T in the methods of Brand, we can ensure that any class that extends SubCollection is a valid parameter.

Here are some code snippets:

Common Lib

public class Brand<T extends SubCollection> extends Entity
{
protected Long id;
protected T subCollection;

public void addSubCollection(T s)
{
        subCollection=s;
        s.setBrandId(this.id);
}
...
}
public class SubCollection extends Entity
{
    protected Long id;
    protected Long brandId;
...
}

Product Project

public class Brand extends com.tura.common.domain.Brand<SubCollection>
{
    protected Boolean includeInSmartSubmit = Boolean.FALSE;
    protected Boolean includeCanadianPricing = Boolean.FALSE;

        public Boolean getIncludeInSmartSubmit()
    {
        return includeInSmartSubmit;
    }

    public void setIncludeInSmartSubmit(Boolean includeInSmartSubmit)
    {
        this.includeInSmartSubmit = includeInSmartSubmit;
    }

    public Boolean getIncludeCanadianPricing()
    {
        return includeCanadianPricing;
    }

    public void setIncludeCanadianPricing(Boolean includeCanadianPricing)
    {
        this.includeCanadianPricing = includeCanadianPricing;
    }
...
}
public class SubCollection extends com.tura.common.domain.SubCollection
{
    protected Boolean includeInSmartSubmit = Boolean.FALSE;
    protected Boolean includeCanadianPricing = Boolean.FALSE;

    public SubCollection(String name)
    {
        super(name);
    }

    public Boolean getIncludeInSmartSubmit()
    {
        return includeInSmartSubmit;
    }

    public Boolean getIncludeCanadianPricing()
    {
        return includeCanadianPricing;
    }
}
stephenh commented 7 years ago

Is the common Brand.subCollection really a T or is it a List<T>? If it's just a T, can you just use inheritance to do what you want, e.g. product Brand extends common.Brand.

pbtura commented 7 years ago

It is actually a List. I was trying to keep the example as simple as possible, but you are correct that normally inheritance would work. Looks like I condensed things down a little TOO far :p

pbtura commented 7 years ago

I managed to come up with a solution that should cover most situations when dealing with generics. It still needs some polish and testing, but if you want to see what I have so far, let me know and I'll submit a PR.