The class diagram

code

Converter interface IConvertor

import org.springframework.util.CollectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public interface IConvertor<D extends DomainModel.P extends BasePo> {

    D convert(P po);

    P convert(D model);

    / * * *@paramPoList database mapping entity class *@return* /
    List<D> convert2ModelList(List<P> poList);

    List<P> convert2PoList(List<D> modelList);
}
Copy the code

The converter abstracts the class, adding methods to get the corresponding domain model or database entity based on the current class parameter generics

package com.xy.ddd.core.convertor;

import com.xy.ddd.core.model.DomainModel;
import com.xy.ddd.core.po.BasePo;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public abstract class AbstractConvertor<D extends DomainModel.P extends BasePo> implements IConvertor<D.P>{
    / * * *@paramPoList database mapping entity class *@return* /
    @Override
    public List<D> convert2ModelList(List<P> poList) {
        if (CollectionUtils.isEmpty(poList)) {
            return new ArrayList<>();
        }
        List<D> list = poList.stream().map(po -> convert(po)).collect(Collectors.toList());
        return list;
    }

    @Override
    public List<P> convert2PoList(List<D> modelList) {
        if (CollectionUtils.isEmpty(modelList)) {
            return new ArrayList<P>();
        }
        List<P> list = modelList.stream().map(model -> convert(model)).collect(Collectors.toList());
        return list;
    }

    public Class<D> getDomainModelClass(a) {
        Type genericSuperclass = this.getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            return (Class)((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
        }
        throw new IllegalStateException("Undefined converter generic");
    }

    public Class<P> getPoClass(a) {
        Type genericSuperclass = this.getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            return (Class)((ParameterizedType) genericSuperclass).getActualTypeArguments()[1];
        }
        throw new IllegalStateException("Undefined converter generic"); }}Copy the code

The default implementation

package com.xy.ddd.core.convertor;

import com.alibaba.fastjson.JSONObject;
import com.xy.ddd.core.annotations.DomainField;
import com.xy.ddd.core.config.DomainRegistryFactory;
import com.xy.ddd.core.constant.LogConstant;
import com.xy.ddd.core.model.DomainModel;
import com.xy.ddd.core.po.BasePo;
import com.xy.ddd.core.service.IDomainService;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.util.Assert;

import java.beans.IntrospectionException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;

public class DefaultConvertor<D extends DomainModel.P extends BasePo> extends AbstractConvertor<D.P> {

    private final List<String> ignoreField = Arrays.asList("serialVersionUID");

    @Override
    public D convert(P po) {
        Class<D> domainModelClass = getDomainModelClass();
        if (domainModelClass == null || po == null) {
            return null;
        }
        D domainModel = null;
        try {
            domainModel = domainModelClass.newInstance();
        } catch (Exception e) {
            LogConstant.frameworkLogger.error("DomainModel instantiation failed, PO = {}", JSONObject.toJSON(po), e);
            return null;
        }

        if (domainModel == null) {
            LogConstant.frameworkLogger.warn("DomainModel instantiation failed, PO = {}", JSONObject.toJSON(po));
            return null;
        }

        Field[] domainFields = FieldUtils.getAllFields(domainModel.getClass());

        try {
            for(Field field : domainFields) { writeProperty(field, po, domainModel); }}catch (Exception e) {
            LogConstant.frameworkLogger.error("DomainModel attribute assignment exception, PO = {}", JSONObject.toJSON(po), e);
            return null;
        }

        return domainModel;
    }

    @Override
    public P convert(D model) {
        Class<P> poClass = getPoClass();
        if (model == null || poClass == null) {
            return null;
        }

         P po = null;
        try {
            po = poClass.newInstance();
        } catch (Exception e) {
            LogConstant.frameworkLogger.error(PoClass instantiation failed, model = {}, JSONObject.toJSON(model), e);
            return null;
        }

        if (po == null) {
            LogConstant.frameworkLogger.warn(PoClass instantiation failed, model = {}, JSONObject.toJSON(model));
            return null;
        }

        Field[] poFields = FieldUtils.getAllFields(po.getClass());

        try {
            for(Field field : poFields) { writeProperty(field, model, po); }}catch (Exception e) {
            LogConstant.frameworkLogger.error(PoClass attribute assignment exception, model = {}", JSONObject.toJSON(model), e);
            return null;
        }

        return po;
    }

    Object readProperty(Field field, Object source) throws IllegalAccessException {
        Assert.notNull(source, "field must not be null");
        Assert.notNull(source, "Source must not be null");

        field.setAccessible(true);
        return field.get(source);
    }

    void writeProperty(Field field, Object source, Object target) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
        Assert.notNull(field, "field must not be null");
        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");

        Object fieldValue = readProperty(field, source);

        if (fieldValue == null || ignoreField.contains(field.getName())) {
            return;
        }

        DomainField annotation = field.getAnnotation(DomainField.class);

        if(annotation ! =null) {
            String domainCode = annotation.code();
            String domainField = annotation.fieldName();

            IDomainService domainService = DomainRegistryFactory.getDomainService(domainCode);

            if (domainService == null) {
                LogConstant.frameworkLogger.error("Using DomainField annotation fields, need to match to realize {@ link com. Xy. DDD. Core. Model. DomainModel}");
                return;
            }

            boolean isSingle = field.getType().getSimpleName().endsWith("List");

            Object value = FieldUtils.readDeclaredField(source, domainField);

            if (isSingle) {
                D domainModel = (D) domainService.findOneByField(domainField, value);
                FieldUtils.writeDeclaredField(target, field.getName(), domainModel);
            } else{ List<D> list = domainService.findListByField(domainField, value); FieldUtils.writeDeclaredField(target, field.getName(), list); }}else{ FieldUtils.writeDeclaredField(target, field.getName(), fieldValue); }}}Copy the code

git

Gitee.com/fly67/ddd-f…