All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.ird.observe.spi.DbModelHelper Maven / Gradle / Ivy

package fr.ird.observe.spi;

/*-
 * #%L
 * ObServe Toolkit :: Common Persistence
 * %%
 * Copyright (C) 2017 - 2019 IRD, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import fr.ird.observe.binder.EntityBinderSupport;
import fr.ird.observe.dto.IdDto;
import fr.ird.observe.dto.data.DataDto;
import fr.ird.observe.dto.form.FormDefinition;
import fr.ird.observe.dto.reference.DataDtoReference;
import fr.ird.observe.dto.reference.DtoReference;
import fr.ird.observe.dto.reference.ReferentialDtoReference;
import fr.ird.observe.dto.referential.ReferentialDto;
import fr.ird.observe.entities.ObserveEntity;
import fr.ird.observe.entities.data.ObserveDataEntity;
import fr.ird.observe.entities.referential.ObserveReferentialEntity;
import fr.ird.observe.spi.context.DataDtoEntityContext;
import fr.ird.observe.spi.context.DataEntityContext;
import fr.ird.observe.spi.context.DataReferenceEntityContext;
import fr.ird.observe.spi.context.DtoEntityContext;
import fr.ird.observe.spi.context.EntityContext;
import fr.ird.observe.spi.context.ReferenceEntityContext;
import fr.ird.observe.spi.context.ReferentialDtoEntityContext;
import fr.ird.observe.spi.context.ReferentialEntityContext;
import fr.ird.observe.spi.context.ReferentialReferenceEntityContext;
import fr.ird.observe.spi.initializer.DtoFormsInitializerSupport;
import fr.ird.observe.spi.initializer.DtoReferencesInitializerSupport;
import fr.ird.observe.spi.initializer.EntitiesBinderInitializerSupport;
import fr.ird.observe.spi.map.DtoToEntityClassMap;
import fr.ird.observe.spi.map.DtoToReferenceClassMap;
import fr.ird.observe.spi.map.ImmutableTypedMap;
import fr.ird.observe.spi.type.TypeTranslators;
import io.ultreia.java4all.application.context.spi.GenerateApplicationComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.topia.persistence.TopiaEntityEnum;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by tchemit on 29/08/17.
 *
 * @author Tony Chemit - [email protected]
 */
@SuppressWarnings("unchecked")
@GenerateApplicationComponent(name = "Persistence Model Helper",
        dependencies = {
                DtoReferencesInitializerSupport.class,
                DtoFormsInitializerSupport.class,
                EntitiesBinderInitializerSupport.class
        })
public class DbModelHelper {

    private static final Logger log = LogManager.getLogger(DtoModelHelper.class);

    private static final DbModelHelper INSTANCE = DbModelHelperApplicationComponent.value();

    private final ImmutableTypedMap referentialDtoContext;
    private final ImmutableTypedMap referentialEntityContext;
    private final ImmutableTypedMap referentialReferenceContext;
    private final ImmutableTypedMap dataDtoContext;
    private final ImmutableTypedMap dataReferenceContext;
    private final ImmutableTypedMap dataEntityContext;

    public DbModelHelper(DtoReferencesInitializerSupport referencesInitializer, DtoFormsInitializerSupport formInitializer, EntitiesBinderInitializerSupport entitiesBinderInitializer) {

        log.info("Persistence model helper initialization  (" + this + ").");

//        DtoReferencesInitializerSupport referencesInitializer = getReferencesInitializer();
//        DtoFormsInitializerSupport formInitializer = getFormInitializer();
//        EntitiesBinderInitializerSupport entitiesBinderInitializer = ServiceLoaders.loadUniqueService(EntitiesBinderInitializerSupport.class);

        DtoToEntityClassMap dtoToEntityClassMapping = entitiesBinderInitializer.getDtoToEntityClassMapping();
        DtoToReferenceClassMap dtoToReferenceClassMapping = referencesInitializer.getDtoToReferenceClassMapping();

        ImmutableTypedMap.Builder referentialDtoContextBuilder = ImmutableTypedMap.builder();
        ImmutableTypedMap.Builder dataDtoContextBuilder = ImmutableTypedMap.builder();

        ImmutableTypedMap.Builder referentialReferenceContextBuilder = ImmutableTypedMap.builder();
        ImmutableTypedMap.Builder dataReferenceContextBuilder = ImmutableTypedMap.builder();

        ImmutableTypedMap.Builder referentialEntityContextBuilder = ImmutableTypedMap.builder();
        ImmutableTypedMap.Builder dataEntityContextBuilder = ImmutableTypedMap.builder();

        int referentialCount = 0;
        for (Class dtoType : referencesInitializer.getReferentialTypes()) {

            registerReferential(dtoType,
                                dtoToReferenceClassMapping,
                                dtoToEntityClassMapping,
                                referencesInitializer,
                                formInitializer,
                                entitiesBinderInitializer,
                                referentialDtoContextBuilder,
                                referentialReferenceContextBuilder,
                                referentialEntityContextBuilder);

            referentialCount++;
        }

        log.debug("Load " + referentialCount + " referential definitions.");

        Collection> dtoTypesWithReference = referencesInitializer.getReferenceToDtoClassMapping().values();
        Collection dtoTypesWithForm = formInitializer.getDtoToFormClassMapping().values();

        int dataCountWithReference = 0;
        int dataCountWithForm = 0;
        Set> dataTypes = new LinkedHashSet<>(referencesInitializer.getDataTypes());
        dataTypes.addAll((Collection) dtoTypesWithForm);
        dataTypes.addAll((Collection) entitiesBinderInitializer.getEntityToDtoClassMapping().values().stream().filter(DtoModelHelper::isData).collect(Collectors.toSet()));
        dataTypes.addAll((Collection) entitiesBinderInitializer.getEntityDtoDataBinders().values().stream().filter(f -> DtoModelHelper.isData(f.getDtoType())).map(EntityBinderSupport::getDtoType).collect(Collectors.toSet()));
        dataTypes.removeAll(referencesInitializer.getReferentialTypes());
        for (Class dtoType : dataTypes) {

            FormDefinition formDefinition = null;
            if (dtoTypesWithForm.contains(dtoType)) {
                dataCountWithForm++;
                formDefinition = formInitializer.getFormDefinitions().get(dtoType);
            }
            if (dtoTypesWithReference.contains(dtoType)) {
                registerDataWithReference(dtoType,
                                          dtoToReferenceClassMapping,
                                          dtoToEntityClassMapping,
                                          referencesInitializer,
                                          formDefinition,
                                          entitiesBinderInitializer,
                                          dataDtoContextBuilder,
                                          dataReferenceContextBuilder,
                                          dataEntityContextBuilder);
                dataCountWithReference++;
            } else {
                registerData(dtoType,
                             dtoToEntityClassMapping,
                             referencesInitializer,
                             formDefinition,
                             entitiesBinderInitializer,
                             dataDtoContextBuilder,
                             dataEntityContextBuilder);
            }

        }

        log.debug("Load " + dataCountWithReference + " reference definitions.");
        log.debug("Load " + dataCountWithForm + " form definitions.");

        log.info("Load " + referencesInitializer.getReferentialBinders().size() + " dto referential binders.");
        log.info("Load " + entitiesBinderInitializer.getEntityDtoReferentialBinders().size() + " entity referential binders.");
        log.info("Load " + referencesInitializer.getDataBinders().size() + " dto data binders.");
        log.info("Load " + entitiesBinderInitializer.getEntityDtoDataBinders().size() + " entity data binders.");


        this.referentialDtoContext = referentialDtoContextBuilder.build();
        this.dataDtoContext = dataDtoContextBuilder.build();

        this.referentialReferenceContext = referentialReferenceContextBuilder.build();
        this.dataReferenceContext = dataReferenceContextBuilder.build();

        this.referentialEntityContext = referentialEntityContextBuilder.build();
        this.dataEntityContext = dataEntityContextBuilder.build();

        log.info("Persistence model helper is initialized (" + this + ").");
    }

    public static boolean equalsDtoTypeAndEntityType(Class one, Class two) {
        return TypeTranslators.getDtoSimplifiedName(one).equals(TypeTranslators.getEntitySimplifiedName(two));
    }

    public static , E extends ObserveEntity> DtoEntityContext fromDto(D dtoType) {
        return fromDto((Class) dtoType.getClass());
    }

    public static , E extends ObserveEntity> DtoEntityContext fromDto(Class dtoType) {
        if (DtoModelHelper.isReferential(dtoType)) {
            return INSTANCE.referentialDtoContext.get(dtoType);
        } else {
            return INSTANCE.dataDtoContext.get(dtoType);
        }
    }

    public static , E extends ObserveReferentialEntity> ReferentialDtoEntityContext fromReferentialDto(D dtoType) {
        return fromReferentialDto((Class) dtoType.getClass());
    }

    public static , E extends ObserveReferentialEntity> ReferentialDtoEntityContext fromReferentialDto(Class dtoType) {
        return INSTANCE.referentialDtoContext.get(dtoType);
    }

    public static , E extends ObserveReferentialEntity> ReferentialReferenceEntityContext fromReferentialReference(R reference) {
        return INSTANCE.referentialReferenceContext.get(reference.getClass());
    }

    public static , E extends ObserveReferentialEntity> ReferentialReferenceEntityContext fromReferentialReference(Class referenceType) {
        return INSTANCE.referentialReferenceContext.get(referenceType);
    }

    public static , E extends ObserveReferentialEntity> ReferentialEntityContext fromReferentialEntity(TopiaEntityEnum entityType) {
        return INSTANCE.referentialEntityContext.get(entityType.getContract());
    }

    public static , E extends ObserveReferentialEntity> ReferentialEntityContext fromReferentialEntity(E entity) {
        return INSTANCE.referentialEntityContext.get(getClass(entity));
    }

    public static , E extends ObserveReferentialEntity> ReferentialEntityContext fromReferentialEntity(Class entityType) {
        return INSTANCE.referentialEntityContext.get(entityType);
    }

    public static , E extends ObserveEntity> EntityContext fromEntity(Class entityType) {
        if (ObserveReferentialEntity.class.isAssignableFrom(entityType)) {
            return INSTANCE.referentialEntityContext.get(entityType);
        } else {
            return INSTANCE.dataEntityContext.get(entityType);
        }
    }

    public static , E extends ObserveEntity> ReferenceEntityContext fromReference(R reference) {
        if (DtoModelHelper.isReferential(reference.getDtoType())) {
            return INSTANCE.referentialReferenceContext.get(reference.getDtoType());
        } else {
            return INSTANCE.dataReferenceContext.get(reference.getDtoType());
        }
    }

    public static , E extends ObserveEntity> ReferenceEntityContext fromReference(Class reference) {
        if (DtoModelHelper.isReferential(reference)) {
            return INSTANCE.referentialReferenceContext.get(reference);
        } else {
            return INSTANCE.dataReferenceContext.get(reference);
        }
    }

    public static , E extends ObserveDataEntity> DataDtoEntityContext fromDataDto(D dto) {
        return fromDataDto((Class) dto.getClass());
    }

    public static , E extends ObserveDataEntity> DataDtoEntityContext fromDataDto(Class dtoType) {
        return INSTANCE.dataDtoContext.get(dtoType);
    }

    public static , E extends ObserveDataEntity> DataReferenceEntityContext fromDataReference(R reference) {
        return INSTANCE.dataReferenceContext.get(reference.getClass());
    }

    public static , E extends ObserveDataEntity> DataReferenceEntityContext fromDataReference(Class referenceType) {
        return INSTANCE.dataReferenceContext.get(referenceType);
    }

    public static , E extends ObserveDataEntity> DataEntityContext fromDataEntity(E entity) {
        return INSTANCE.dataEntityContext.get(getClass(entity));
    }

    public static , E extends ObserveDataEntity> DataEntityContext fromDataEntity(Class entityType) {
        return INSTANCE.dataEntityContext.get(entityType);
    }

    private static Class getClass(Object entity) {
        if (entity.getClass().getName().contains("net.bytebuddy")) {
            return entity.getClass().getInterfaces()[0];
        }
        if (entity.getClass().getName().contains("HibernateProxy")) {
            return entity.getClass().getInterfaces()[0];
        }
        return entity.getClass();
    }

    private static , E extends ObserveReferentialEntity> void registerReferential(Class dtoType,
                                                                                                                                                    DtoToReferenceClassMap dtoToReferenceClassMapping,
                                                                                                                                                    DtoToEntityClassMap dtoToEntityClassMap,
                                                                                                                                                    DtoReferencesInitializerSupport referencesInitializer,
                                                                                                                                                    DtoFormsInitializerSupport formInitializer,
                                                                                                                                                    EntitiesBinderInitializerSupport initializer,
                                                                                                                                                    ImmutableTypedMap.Builder referentialDtoContextBuilder,
                                                                                                                                                    ImmutableTypedMap.Builder referentialReferenceContextBuilder,
                                                                                                                                                    ImmutableTypedMap.Builder referentialEntityContextBuilder
    ) {

        referentialDtoContextBuilder.put(dtoType, new ReferentialDtoEntityContext<>(dtoType, referencesInitializer, formInitializer, initializer));

        Class referenceType = dtoToReferenceClassMapping.forReferential(dtoType);
        referentialReferenceContextBuilder.put(dtoType, new ReferentialReferenceEntityContext<>(referenceType, referencesInitializer, initializer));

        Class entityType = dtoToEntityClassMap.forReferential(dtoType);
        referentialEntityContextBuilder.put(entityType, new ReferentialEntityContext<>(entityType, referencesInitializer, initializer));


    }

    private static  void registerData(Class dtoType,
                                                                                      DtoToEntityClassMap dtoToEntityClassMap,
                                                                                      DtoReferencesInitializerSupport referencesInitializer,
                                                                                      FormDefinition formDefinition,
                                                                                      EntitiesBinderInitializerSupport initializer,
                                                                                      ImmutableTypedMap.Builder dataDtoContextBuilder,
                                                                                      ImmutableTypedMap.Builder dataEntityContextBuilder) {

        dataDtoContextBuilder.put(dtoType, new DataDtoEntityContext<>(dtoType, referencesInitializer, formDefinition, initializer));

        Class entityType = dtoToEntityClassMap.forData(dtoType);
        if (equalsDtoTypeAndEntityType(dtoType, entityType)) {
            // main dto, keep this link only since when coming from entity, we only can bind to main dto
            dataEntityContextBuilder.put(entityType, new DataEntityContext<>(entityType, referencesInitializer, initializer));
        }

    }

    private static , E extends ObserveDataEntity> void registerDataWithReference(Class dtoType,
                                                                                                                                     DtoToReferenceClassMap dtoToReferenceClassMapping,
                                                                                                                                     DtoToEntityClassMap dtoToEntityClassMap,
                                                                                                                                     DtoReferencesInitializerSupport referencesInitializer,
                                                                                                                                     FormDefinition formDefinition,
                                                                                                                                     EntitiesBinderInitializerSupport initializer,
                                                                                                                                     ImmutableTypedMap.Builder dataDtoContextBuilder,
                                                                                                                                     ImmutableTypedMap.Builder dataReferenceContextBuilder,
                                                                                                                                     ImmutableTypedMap.Builder dataEntityContextBuilder) {

        dataDtoContextBuilder.put(dtoType, new DataDtoEntityContext<>(dtoType, referencesInitializer, formDefinition, initializer));

        Class referenceType = dtoToReferenceClassMapping.forData(dtoType);
        dataReferenceContextBuilder.put(dtoType, new DataReferenceEntityContext<>(referenceType, referencesInitializer, initializer));

        Class entityType = dtoToEntityClassMap.forData(dtoType);
        if (equalsDtoTypeAndEntityType(dtoType, entityType)) {
            // main dto, keep this link only since when coming from entity, we only can bind to main dto
            dataEntityContextBuilder.put(entityType, new DataEntityContext<>(entityType, referencesInitializer, initializer));
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy