com.alon.spring.crud.service.CrudService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-crud-base Show documentation
Show all versions of spring-crud-base Show documentation
Projeto base para criação de serviços e recusos de CRUD com Spring Data JPA.
package com.alon.spring.crud.service;
import com.alon.querydecoder.Expression;
import com.alon.querydecoder.SingleExpression;
import com.alon.spring.crud.model.BaseEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public interface CrudService {
public R getRepository();
default Page list() {
return this.list(0, Integer.MAX_VALUE);
}
default Page list(SingleExpression order) {
return this.list(0, Integer.MAX_VALUE, order);
}
default Page list(int page, int size) {
return this.getRepository().findAll(PageRequest.of(page, size));
}
default Page list(int page, int size, SingleExpression order) {
return this.getRepository().findAll(Hidden.buildPageable(page, size, order));
}
default Page list(Specification specification, int page, int size) {
return this.getRepository().findAll(specification, PageRequest.of(page, size));
}
default Page list(Specification specification, int page, int size, SingleExpression order) {
return this.getRepository().findAll(specification, Hidden.buildPageable(page, size, order));
}
default E create(@Valid E entity) throws CreateException {
try {
entity = Hidden.executeHook(this, entity, LifeCycleHook.BEFORE_CREATE);
entity = (E) this.getRepository().save(entity);
return Hidden.executeHook(this, entity, LifeCycleHook.AFTER_CREATE);
} catch (Throwable ex) {
throw new CreateException(ex.getMessage(), ex);
}
}
default > E read(ID id) {
return (E) this.getRepository().findById(id).get();
}
default E update(@Valid E entity) throws UpdateException {
if (entity.id() == null)
throw new UpdateException("Unmanaged entity. Use the create method.");
try {
entity = Hidden.executeHook(this, entity, LifeCycleHook.BEFORE_UPDATE);
entity = this.create(entity);
return Hidden.executeHook(this, entity, LifeCycleHook.AFTER_UPDATE);
} catch (Throwable ex) {
throw new UpdateException(ex.getMessage(), ex);
}
}
default void delete(ID id) throws DeleteException {
try {
Hidden.executeHook(this, id, LifeCycleHook.BEFORE_DELETE);
this.getRepository().deleteById(id);
Hidden.executeHook(this, id, LifeCycleHook.AFTER_DELETE);
} catch (Throwable ex) {
throw new DeleteException(ex.getMessage(), ex);
}
}
default CrudService addBeforeCreateHook(Function function) {
Hidden.getServiceHooks(this).get(LifeCycleHook.BEFORE_CREATE).add(function);
return this;
}
default CrudService addAfterCreateHook(Function function) {
Hidden.getServiceHooks(this).get(LifeCycleHook.AFTER_CREATE).add(function);
return this;
}
default CrudService addBeforeUpdateHook(Function function) {
Hidden.getServiceHooks(this).get(LifeCycleHook.BEFORE_UPDATE).add(function);
return this;
}
default CrudService addAfterUpdateHook(Function function) {
Hidden.getServiceHooks(this).get(LifeCycleHook.AFTER_UPDATE).add(function);
return this;
}
default CrudService addBeforeDeleteHook(Function function) {
Hidden.getServiceHooks(this).get(LifeCycleHook.BEFORE_DELETE).add(function);
return this;
}
default CrudService addAfterDeleteHook(Function function) {
Hidden.getServiceHooks(this).get(LifeCycleHook.AFTER_DELETE).add(function);
return this;
}
enum LifeCycleHook {
BEFORE_CREATE,
AFTER_CREATE,
BEFORE_UPDATE,
AFTER_UPDATE,
BEFORE_DELETE,
AFTER_DELETE
}
/**
* This class has the function of restricting methods,
* because private methods are not allowed in interfaces.
*/
class Hidden {
private static Map>> GLOBAL_HOOKS = new HashMap<>();
private static Pageable buildPageable(int page, int size, SingleExpression orders) {
return PageRequest.of(page, size, buildSort(orders));
}
private static Sort buildSort(SingleExpression order) {
List orders = new ArrayList<>();
do {
boolean desc = order.getValue().equalsIgnoreCase("DESC");
if (desc)
orders.add(Order.desc(order.getField()));
else
orders.add(Order.asc(order.getField()));
order = (SingleExpression) order.getNext();
} while (order != null);
return Sort.by(orders);
}
private static P executeHook(S service, P param, LifeCycleHook hookType) throws Throwable {
List hooks = getHook(service, hookType);
for (Function hook : hooks)
param = (P) hook.apply(param);
return param;
}
private static List getHook(T service, LifeCycleHook hookType) {
return getServiceHooks(service).get(hookType);
}
private static Map> getServiceHooks(T service) {
Map> hooks = GLOBAL_HOOKS.get(service);
if (hooks == null)
hooks = initHooks(service);
return hooks;
}
private static Map> initHooks(T service) {
Map> hooks = new HashMap<>();
for (LifeCycleHook hook : LifeCycleHook.values())
hooks.put(hook, new ArrayList<>());
GLOBAL_HOOKS.put(service, hooks);
return hooks;
}
}
}