orika-mapper / orika

Simpler, better and faster Java bean mapping framework
http://orika-mapper.github.io/orika-docs/
Apache License 2.0
1.29k stars 268 forks source link

Mapping a flat entity with Jaxb generated classes #235

Open Shinryuken opened 7 years ago

Shinryuken commented 7 years ago

Hi, i'm having a hard time trying to map a flat entity with a nested Jaxb generated structure.

I did not found a method to change the behaviour of the xsd generator, it will create those strange case issues between fields names and getters/setters method names, it's creating wrapper classes for multioccurence elements too with only the getter logic, i noticed the ScoringClassMapBuilder example on the test packages but i keep getting errors, i could change eventually the flat entity field names if necessary (the flat entity was made using all the leaf fields of the nested structure), this is an example with the same structure of the project:

(you can find all the classes attached)

I'm sorry if this is not the right place to ask, thanks in advance.

package com.mapping.example.orika.destination;
import java.math.BigInteger;

public class PCTYPE {

    protected BigInteger revision;
    protected String pcname;
    protected COMPONENTSTYPE components;

    public BigInteger getREVISION() {
        return revision;
    }

    public void setREVISION(BigInteger value) {
        this.revision = value;
    }

    public String getPCNAME() {
        return pcname;
    }

    public void setPCNAME(String value) {
        this.pcname = value;
    }

    public COMPONENTSTYPE getCOMPONENTSTYPE() {
        return components;
    }

    public void setCOMPONENTSTYPE(COMPONENTSTYPE value) {
        this.components = value;
    }

    @Override
    public String toString() {
        return "PCTYPE [revision=" + revision + ", pcname=" + pcname + ", components=" + components + "]";
    }

}
package com.mapping.example.orika.destination;

import java.util.ArrayList;
import java.util.List;

public class COMPONENTSTYPE {

    protected List<COMPONENTTYPE> component;

    public List<COMPONENTTYPE> getCOMPONENT() {
        if (component == null) {
            component = new ArrayList<COMPONENTTYPE>();
        }
        return this.component;
    }

    @Override
    public String toString() {
        return "COMPONENTSTYPE [component=" + component + "]";
    }

}
package com.mapping.example.orika.destination;
import java.math.BigInteger;
import javax.xml.datatype.XMLGregorianCalendar;

public class COMPONENTTYPE {

    protected String componentname;
    protected BigInteger version;
    protected XMLGregorianCalendar creationdate;
    protected INSTALLATIONSTEPSTYPE installationsteps;
    protected VENDORINFOTYPE vendorinfo;

    public String getCOMPONENTNAME() {
        return componentname;
    }

    public void setCOMPONENTNAME(String value) {
        this.componentname = value;
    }

    public BigInteger getVERSION() {
        return version;
    }

    public void setVERSION(BigInteger value) {
        this.version = value;
    }

    public XMLGregorianCalendar getCREATIONDATE() {
        return creationdate;
    }

    public void setCREATIONDATE(XMLGregorianCalendar value) {
        this.creationdate = value;
    }

    public INSTALLATIONSTEPSTYPE getINSTALLATIONSTEPS() {
        return installationsteps;
    }

    public void setINSTALLATIONSTEPS(INSTALLATIONSTEPSTYPE value) {
        this.installationsteps = value;
    }

    public VENDORINFOTYPE getVENDORINFO() {
        return vendorinfo;
    }

    public void setVENDORINFO(VENDORINFOTYPE value) {
        this.vendorinfo = value;
    }

    @Override
    public String toString() {
        return "COMPONENTTYPE [componentname=" + componentname + ", version=" + version + ", creationdate="
                + creationdate + ", installationsteps=" + installationsteps + ", vendorinfo=" + vendorinfo + "]";
    }

}
package com.mapping.example.orika.source;
import java.util.Date;

public class PersonalComputerDto {

    private Integer revision;
    private String pcname;
    private String componentname;
    private Integer version;
    private Date creationdate;
    private Integer stepnumber;
    private String stepdescription;
    private String manufacturername;
    private Integer vendorid;

    public Integer getRevision() {
        return revision;
    }
    public void setRevision(Integer revision) {
        this.revision = revision;
    }
    public String getPcname() {
        return pcname;
    }
    public void setPcname(String pcname) {
        this.pcname = pcname;
    }
    public String getComponentname() {
        return componentname;
    }
    public void setComponentname(String componentname) {
        this.componentname = componentname;
    }
    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
    public Date getCreationdate() {
        return creationdate;
    }
    public void setCreationdate(Date creationdate) {
        this.creationdate = creationdate;
    }
    public Integer getStepnumber() {
        return stepnumber;
    }
    public void setStepnumber(Integer stepnumber) {
        this.stepnumber = stepnumber;
    }
    public String getStepdescription() {
        return stepdescription;
    }
    public void setStepdescription(String stepdescription) {
        this.stepdescription = stepdescription;
    }
    public String getManufacturername() {
        return manufacturername;
    }
    public void setManufacturername(String manufacturername) {
        this.manufacturername = manufacturername;
    }
    public Integer getVendorid() {
        return vendorid;
    }
    public void setVendorid(Integer vendorid) {
        this.vendorid = vendorid;
    }
}
package com.mapping.example.orika;

import java.util.Calendar;

import com.mapping.example.orika.destination.PCTYPE;
import com.mapping.example.orika.source.PersonalComputerDto;

import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.ScoringClassMapBuilder;
import ma.glasnost.orika.metadata.Type;
import ma.glasnost.orika.metadata.TypeBuilder;

public class OrikaMapTest {

    public static void main(String[] args) {

            Type<PersonalComputerDto> typeOf_FlatData = new TypeBuilder<PersonalComputerDto>(){}.build();

            Type<PCTYPE> typeOf_Pc = new TypeBuilder<PCTYPE>(){}.build();

            MapperFactory mapperFactory = new DefaultMapperFactory.Builder()
                .classMapBuilderFactory(new ScoringClassMapBuilder.Factory())
                .build();

            mapperFactory.classMap(typeOf_FlatData, typeOf_Pc).byDefault().register();

            MapperFacade mapper = mapperFactory.getMapperFacade();

            PersonalComputerDto pcd = new PersonalComputerDto();

            pcd.setComponentname("componentname");
            pcd.setCreationdate(Calendar.getInstance().getTime());
            pcd.setManufacturername("manufacturername");
            pcd.setPcname("pcname");
            pcd.setRevision(1);
            pcd.setStepdescription("stepdescription");
            pcd.setStepnumber(2);
            pcd.setVendorid(3);
            pcd.setVersion(4);

            PCTYPE pctype = mapper.map(pcd, typeOf_FlatData, typeOf_Pc);

            System.out.println(pctype);
        }

}

flat_jaxb_orika.zip

PsionOmikron commented 6 years ago

The JAXB Setters Plugin will modify the behavior of generation to generate setters for lists.

If you're not able to correct the generation, here is some code I wrote awhile back to address this problem for lists of Strings:

public static class ElementPropertyResolver extends IntrospectorPropertyResolver
{
    private static final Type<?> STRING_LIST_TYPE = TypeFactory.valueOf(List.class, String.class);

    @Override
    protected Property getProperty(java.lang.reflect.Type type,
                                   String expr,
                                   boolean isNestedLookup,
                                   Property owner) throws MappingException
    {
        try
        {
            return super.getProperty(type, expr, isNestedLookup, null);
        }
        catch (MappingException e)
        {
            try
            {
                Type<?> genericType = TypeFactory.valueOf(type);
                String getter = "get" + StringUtils.capitalize(expr) + "()";

                Property property = Property.Builder.propertyFor(genericType, expr)
                    .type(STRING_LIST_TYPE).getter(getter).setter(getter).build(this);

                return new ListAddAllProperty(property);
            }
            catch (MappingException e2)
            {
                throw e; // throw the original exception
            }
        }
    }
}

private static class ListAddAllProperty extends Property
{
    public ListAddAllProperty(Property property)
    {
        super(property.getExpression(),
              property.getName(),
              property.getGetter(),
              property.getSetter() + ".addAll(%s)",
              property.getType(),
              property.getElementType(),
              property.getContainer());
    }
}

And to register it:

new DefaultMapperFactory.Builder().propertyResolverStrategy(new ElementPropertyResolver())