Merge pull request #2373 from FOCONIS/pr/enh/post_process_find_controller

Allow post-processing in BeanFindController
This commit is contained in:
Rob Bygrave
2021-09-16 11:26:34 +12:00
committed by GitHub
7 changed files with 315 additions and 1 deletions
@@ -50,4 +50,17 @@ public interface BeanFindController {
*/
<T> BeanCollection<T> findMany(BeanQueryRequest<T> request);
/**
* Allows post-processing of the find result.
*/
default <T> BeanCollection<T> postProcessMany(BeanQueryRequest<T> request, BeanCollection<T> result) {
return result;
}
/**
* Allows post-processing of the find result.
*/
default <T> T postProcess(BeanQueryRequest<T> request, T result) {
return result;
};
}
@@ -131,6 +131,10 @@ public final class DefaultOrmQueryEngine implements OrmQueryEngine {
result = queryEngine.findMany(request);
}
if (finder != null) {
result = finder.postProcessMany(request, result);
}
SpiQuery<T> query = request.query();
if (result != null && request.isBeanCachePutMany()) {
@@ -171,6 +175,10 @@ public final class DefaultOrmQueryEngine implements OrmQueryEngine {
result = queryEngine.find(request);
}
if (finder != null) {
result = finder.postProcess(request, result);
}
if (result != null && request.isBeanCachePut()) {
request.descriptor().cacheBeanPut((EntityBean) result);
}
@@ -10,10 +10,18 @@ import org.junit.jupiter.api.Test;
import org.tests.example.ModUuidGenerator;
import org.tests.model.basic.EBasic;
import org.tests.model.basic.ECustomId;
import org.tests.model.controller.FindControllerMain;
import org.tests.model.controller.SoftRefA;
import org.tests.model.controller.SoftRefB;
import org.tests.model.controller.TestBeanFindController;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class BeanFindControllerTest extends BaseTestCase {
@@ -116,4 +124,91 @@ public class BeanFindControllerTest extends BaseTestCase {
b.setName("47");
return b;
}
@Test
public void testPostProcess() {
Database db = prepareSoftRefs();
final FindControllerMain controllerDbA = db.find(FindControllerMain.class, 1);
assertThat(controllerDbA).isNotNull();
assertThat(controllerDbA.getTarget())
.isNotNull()
.isInstanceOf(SoftRefA.class)
.hasFieldOrPropertyWithValue("title", "softRefA");
final FindControllerMain controllerDbB = db.find(FindControllerMain.class, 2);
assertThat(controllerDbB).isNotNull();
assertThat(controllerDbB.getTarget())
.isNotNull()
.isInstanceOf(SoftRefB.class)
.hasFieldOrPropertyWithValue("title", "softRefB");
}
@Test
public void testPostProcessFindMany() {
Database db = prepareSoftRefs();
final List<FindControllerMain> controllers = db.find(FindControllerMain.class).orderById(true).findList();
assertThat(controllers).hasSize(2);
final FindControllerMain controllerDbA = controllers.get(0);
assertThat(controllerDbA.getId()).isEqualTo(1);
assertThat(controllerDbA.getTarget())
.isNotNull()
.isInstanceOf(SoftRefA.class)
.hasFieldOrPropertyWithValue("title", "softRefA");
final FindControllerMain controllerDbB = controllers.get(1);
assertThat(controllerDbB.getId()).isEqualTo(2);
assertThat(controllerDbB.getTarget())
.isNotNull()
.isInstanceOf(SoftRefB.class)
.hasFieldOrPropertyWithValue("title", "softRefB");
}
private Database prepareSoftRefs() {
DatabaseConfig config = new DatabaseConfig();
config.setName("h2otherfind");
config.loadFromProperties();
config.setDdlGenerate(true);
config.setDdlRun(true);
config.setDdlExtra(false);
config.setRegister(false);
config.setDefaultServer(false);
config.add(new ModUuidGenerator());
config.getClasses().add(FindControllerMain.class);
config.getClasses().add(SoftRefA.class);
config.getClasses().add(SoftRefB.class);
config.getFindControllers().add(new TestBeanFindController());
Database db = DatabaseFactory.create(config);
final SoftRefA softRefA = new SoftRefA();
softRefA.setTitle("softRefA");
db.save(softRefA);
final SoftRefB softRefB = new SoftRefB();
softRefB.setTitle("softRefB");
db.save(softRefB);
final FindControllerMain main1 = new FindControllerMain();
main1.setTargetId(softRefA.getId());
main1.setTargetTableName("soft_ref_a");
db.save(main1);
final FindControllerMain main2 = new FindControllerMain();
main2.setTargetId(softRefB.getId());
main2.setTargetTableName("soft_ref_b");
db.save(main2);
return db;
}
}
@@ -0,0 +1,51 @@
package org.tests.model.controller;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
@Entity
public class FindControllerMain {
@Id
private Integer id;
private Integer targetId;
private String targetTableName;
@Transient
private Object target;
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public Integer getTargetId() {
return targetId;
}
public void setTargetId(final Integer targetId) {
this.targetId = targetId;
}
public String getTargetTableName() {
return targetTableName;
}
public void setTargetTableName(final String targetTableName) {
this.targetTableName = targetTableName;
}
public Object getTarget() {
return target;
}
public void setTarget(final Object target) {
this.target = target;
}
}
@@ -0,0 +1,29 @@
package org.tests.model.controller;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class SoftRefA {
@Id
private Integer id;
private String title;
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}
@@ -0,0 +1,29 @@
package org.tests.model.controller;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class SoftRefB {
@Id
private Integer id;
private String title;
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}
@@ -0,0 +1,89 @@
package org.tests.model.controller;
import io.ebean.bean.BeanCollection;
import io.ebean.event.BeanFindController;
import io.ebean.event.BeanQueryRequest;
import io.ebean.plugin.BeanType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestBeanFindController implements BeanFindController {
@Override
public boolean isRegisterFor(final Class<?> cls) {
return cls.isAssignableFrom(FindControllerMain.class);
}
@Override
public boolean isInterceptFind(final BeanQueryRequest<?> request) {
return false;
}
@Override
public <T> T find(final BeanQueryRequest<T> request) {
return null;
}
@Override
public boolean isInterceptFindMany(final BeanQueryRequest<?> request) {
return false;
}
@Override
public <T> BeanCollection<T> findMany(final BeanQueryRequest<T> request) {
return null;
}
@Override
public <T> BeanCollection<T> postProcessMany(final BeanQueryRequest<T> request, final BeanCollection<T> result) {
Map<Class<?>, List<Integer>> elementsMap = new HashMap<>();
Map<Class<?>, Map<Integer, FindControllerMain>> controllerLookup = new HashMap<>();
for (Object entry : result.getActualEntries()) {
FindControllerMain findControllerMain = (FindControllerMain) entry;
Class<?> beanType = beanTypeFor(findControllerMain.getTargetTableName(), request);
if (beanType != null) {
elementsMap.computeIfAbsent(beanType, key -> new ArrayList<>()).add(findControllerMain.getTargetId());
controllerLookup.computeIfAbsent(beanType, key -> new HashMap<>()).put(findControllerMain.getTargetId(), findControllerMain);
}
}
elementsMap.forEach((beanType, ids) -> {
final Map<Integer, FindControllerMain> idLookup = controllerLookup.get(beanType);
request.getEbeanServer().find(beanType).where()
.idIn(ids).setMapKey("id")
.findMap().forEach((id, bean) -> idLookup.get((Integer) id).setTarget(bean));
});
return result;
}
@Override
public <T> T postProcess(final BeanQueryRequest<T> request, final T result) {
FindControllerMain findControllerMain = (FindControllerMain) result;
Class<?> beanType = beanTypeFor(findControllerMain.getTargetTableName(), request);
if (beanType != null) {
findControllerMain.setTarget(request.getEbeanServer().find(beanType, findControllerMain.getTargetId()));
}
return result;
}
private Class<?> beanTypeFor(String tableName, BeanQueryRequest<?> request) {
List<? extends BeanType<?>> types = request.getEbeanServer()
.getPluginApi().getBeanTypes(tableName);
for (BeanType<?> type : types) {
if (type.isInheritanceRoot()) {
return type.getBeanType();
}
}
return null;
}
}