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

com.alon.spring.crud.domain.service.MasterAsOwnerNestedCrudService Maven / Gradle / Ivy

Go to download

Fornece implementação básica e expansível para criação API's CRUD com Spring Boot e Spring Data JPA.

There is a newer version: 1.0.9
Show newest version
package com.alon.spring.crud.domain.service;

import com.alon.spring.crud.domain.model.BaseEntity;
import com.alon.spring.crud.domain.repository.CrudRepository;
import com.alon.spring.crud.domain.repository.EntityGraphResolver;
import com.alon.spring.crud.domain.service.exception.NotFoundException;
import com.cosium.spring.data.jpa.entity.graph.domain.DynamicEntityGraph;
import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph;
import org.modelmapper.ModelMapper;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.Join;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public interface MasterAsOwnerNestedCrudService<
        MASTER_ENTITY_ID_TYPE extends Serializable,
        MASTER_ENTITY_TYPE extends BaseEntity,
        MASTER_REPOSITORY_TYPE extends CrudRepository,
        NESTED_ENTITY_ID_TYPE extends Serializable,
        NESTED_ENTITY_TYPE extends BaseEntity>
extends NestedCrudService<
        MASTER_ENTITY_ID_TYPE, MASTER_ENTITY_TYPE,
        NESTED_ENTITY_ID_TYPE, NESTED_ENTITY_TYPE> {

    String ID_FIELD_NAME = "id";
    ModelMapper MAPPER = new ModelMapper();

    Supplier> getNestedGetter(MASTER_ENTITY_TYPE masterEntity);
    Consumer getNestedSetter(MASTER_ENTITY_TYPE masterEntity);
    MASTER_REPOSITORY_TYPE getMasterRepository();
    String getNestedFieldName();

    @Override
    default Collection search(MASTER_ENTITY_ID_TYPE masterId, SearchCriteria searchCriteria) {
        List expand = normalizeExpand(List.copyOf(searchCriteria.getExpand()));

        EntityGraph graph = new DynamicEntityGraph(expand);

        Optional masterEntityOpt = getMasterRepository().findById(masterId, graph);

        return masterEntityOpt
                .map(this::getNestedGetter)
                .map(Supplier::get)
                .orElseThrow(() -> new NotFoundException(
                        String.format("Master resource with id %s was not found", masterId)));
    }

    @Override
    default NESTED_ENTITY_TYPE read(
            MASTER_ENTITY_ID_TYPE masterId, NESTED_ENTITY_ID_TYPE nestedId, List expand) {

        executeBeforeReadHooks(nestedId, masterId);

        Specification specification = getFindByIdSpecification(masterId, nestedId);

        expand = normalizeExpand(expand);

        Optional masterEntityOpt;
        
        if (expand != null && !expand.isEmpty())
            masterEntityOpt = getMasterRepository().findOne(specification, new DynamicEntityGraph(expand));
        else
            masterEntityOpt = getMasterRepository().findOne(specification);

        NESTED_ENTITY_TYPE entity = masterEntityOpt
                .map(this::getNestedGetter)
                .map(Supplier::get)
                .map(Collection::stream)
                .map(Stream::findFirst)
                .map(Optional::get)
                .orElseThrow(() -> new NotFoundException(
                        String.format("Resource not found with masterId %s and nestedId %s", masterId, nestedId)));

        executeAfterReadHooks(entity, masterId);

        return entity;
    }

    @Override
    default NESTED_ENTITY_TYPE create(MASTER_ENTITY_ID_TYPE masterId, NESTED_ENTITY_TYPE nestedEntity) {
        executeBeforeCreateHooks(nestedEntity, masterId);

        MASTER_ENTITY_TYPE masterEntity = getMasterRepository()
                .findById(masterId)
                .orElseThrow(() -> new NotFoundException(
                        String.format("Master resource with id %s was not found", masterId)));

        getNestedSetter(masterEntity).accept(nestedEntity);

        masterEntity = getMasterRepository().save(masterEntity);

        Collection nestedCollection = getNestedGetter(masterEntity).get();

        NESTED_ENTITY_TYPE entity = nestedCollection.stream()
                .skip(nestedCollection.size() - 1)
                .findFirst()
                .get();

        executeAfterCreateHooks(entity, masterId);

        return entity;
    }

    @Override
    default NESTED_ENTITY_TYPE update(MASTER_ENTITY_ID_TYPE masterId,
            NESTED_ENTITY_ID_TYPE nestedId, NESTED_ENTITY_TYPE nestedEntity) {
        executeBeforeUpdateHooks(nestedEntity, masterId);

        Specification specification = getFindByIdSpecification(masterId, nestedId);

        Optional masterEntityOpt = getMasterRepository().findOne(specification);

        NESTED_ENTITY_TYPE persistedNestedEntity = masterEntityOpt
                .map(this::getNestedGetter)
                .map(Supplier::get)
                .map(Collection::stream)
                .map(Stream::findFirst)
                .map(Optional::get)
                .orElseThrow(() -> new NotFoundException(
                        String.format("Resource not found with masterId %s and nestedId %s", masterId, nestedId)));

        MAPPER.map(nestedEntity, persistedNestedEntity);

        getMasterRepository().save(masterEntityOpt.get());

        executeAfterUpdateHooks(persistedNestedEntity, masterId);

        return persistedNestedEntity;
    }

    @Override
    default void delete(MASTER_ENTITY_ID_TYPE masterId, NESTED_ENTITY_ID_TYPE nestedId) {
        executeBeforeDeleteHooks(nestedId, masterId);

        MASTER_ENTITY_TYPE masterEntity = getMasterRepository()
                .findOne(getFindByIdSpecification(masterId, nestedId))
                .orElseThrow(() -> new NotFoundException(
                        String.format("Resource not found with masterId %s and nestedId %s",
                                masterId, nestedId)));

        getNestedGetter(masterEntity).get().clear();

        getMasterRepository().save(masterEntity);

        executeBeforeDeleteHooks(nestedId, masterId);
    }

    default Specification getFindByIdSpecification(MASTER_ENTITY_ID_TYPE masterId, NESTED_ENTITY_ID_TYPE nestedId) {
        return ((root, query, criteriaBuilder) -> {
            Join nested = root.join(getNestedFieldName());
            return criteriaBuilder.and(criteriaBuilder.equal(root.get(ID_FIELD_NAME), masterId),
                    criteriaBuilder.equal(nested.get(ID_FIELD_NAME), nestedId));
        });
    }

    default List normalizeExpand(List expand) {
        return expand.stream()
                .map(field -> field.startsWith(getNestedFieldName()) ?
                        field
                        :
                        String.format("%s.%s", getNestedFieldName(), field))
                .collect(Collectors.toList());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy