Skip to content

Commit

Permalink
Merge pull request #38116 from gmuellerinform/panace-data-rest-many-t…
Browse files Browse the repository at this point in the history
…o-one

Support ManyToOne queries in Panache REST resource
  • Loading branch information
geoand authored Jan 12, 2024
2 parents 7d64a5e + bf8e3f5 commit 96a7361
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;

import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -29,4 +30,20 @@ void shouldCopyAdditionalMethodsAsResources() {
.and().body("name", is("full collection"));
}

@Test
void shouldReturnItemsForFullCollection() {
given().accept("application/json")
.when().get("/items?collection.id=full")
.then().statusCode(200)
.body("$", hasSize(2));
}

@Test
void shouldReturnNoItemsForEmptyCollection() {
given().accept("application/json")
.when().get("/items?collection.id=empty")
.then().statusCode(200)
.body("$", hasSize(0));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource
parameters.add(param("size", int.class, intType()));
parameters.add(param("uriInfo", UriInfo.class));
parameters.add(param("namedQuery", String.class));
parameters.addAll(compatibleFieldsForQuery);
for (SignatureMethodCreator.Parameter param : compatibleFieldsForQuery) {
parameters.add(param(
param.getName().replace(".", "__"),
param.getClazz()));
}
MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(getMethodName(), classCreator,
isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()),
parameters.toArray(new SignatureMethodCreator.Parameter[0]));
Expand Down Expand Up @@ -271,7 +275,11 @@ private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resou
List<SignatureMethodCreator.Parameter> parameters = new ArrayList<>();
parameters.add(param("sort", List.class, parameterizedType(classType(List.class), classType(String.class))));
parameters.add(param("namedQuery", String.class));
parameters.addAll(compatibleFieldsForQuery);
for (SignatureMethodCreator.Parameter param : compatibleFieldsForQuery) {
parameters.add(param(
param.getName().replace(".", "__"),
param.getClazz()));
}
MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(getMethodName(), classCreator,
isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()),
parameters.toArray(new SignatureMethodCreator.Parameter[0]));
Expand Down Expand Up @@ -321,13 +329,14 @@ public ResultHandle list(BytecodeCreator creator, ResourceMetadata resourceMetad
ResultHandle queryList = creator.newInstance(ofConstructor(ArrayList.class));
for (Map.Entry<String, ResultHandle> field : fieldValues.entrySet()) {
String fieldName = field.getKey();
String paramName = fieldName.replace(".", "__");
ResultHandle fieldValueFromQuery = field.getValue();
BytecodeCreator fieldValueFromQueryIsSet = creator.ifNotNull(fieldValueFromQuery).trueBranch();
fieldValueFromQueryIsSet.invokeInterfaceMethod(ofMethod(List.class, "add", boolean.class, Object.class),
queryList, fieldValueFromQueryIsSet.load(fieldName + "=:" + fieldName));
queryList, fieldValueFromQueryIsSet.load(fieldName + "=:" + paramName));
fieldValueFromQueryIsSet.invokeInterfaceMethod(
ofMethod(Map.class, "put", Object.class, Object.class, Object.class),
dataParams, fieldValueFromQueryIsSet.load(fieldName), fieldValueFromQuery);
dataParams, fieldValueFromQueryIsSet.load(paramName), fieldValueFromQuery);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

public final class EntityTypeUtils {

// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5
public static final int ACC_STATIC = 0x0008;
public static final int ACC_FINAL = 0x0010;

private EntityTypeUtils() {

}
Expand All @@ -25,7 +29,46 @@ public static Map<String, Type> getEntityFields(IndexView index, String entityTy
ClassInfo currentEntityClass = index.getClassByName(entityTypeName);
while (currentEntityClass != null) {
for (FieldInfo field : currentEntityClass.fields()) {
// skip static fields
if ((field.flags() & ACC_STATIC) != 0) {
continue;
}
// skip final fields
if ((field.flags() & ACC_FINAL) != 0) {
continue;
}
// skip fields with Transient annotation
if (field.hasAnnotation(DotName.createSimple("jakarta.persistence.Transient"))) {
continue;
}

fields.put(field.name(), field.type());

// if the field is a ManyToOne relation, add the Id field of the relation to the fields map
if (field.type().kind() == Type.Kind.CLASS
&& field.hasAnnotation(DotName.createSimple("jakarta.persistence.ManyToOne"))) {
// get the class info for the relation field
ClassInfo currentRelationClass = index.getClassByName(field.type().name());
while (currentRelationClass != null) {
// get the field with Id annotation
FieldInfo relationIdField = currentRelationClass.fields().stream().filter((relationField) -> {
return relationField.hasAnnotation(DotName.createSimple("jakarta.persistence.Id"));
}).findFirst().orElse(null);
// if the field is not null, add it to the fields map
if (relationIdField != null) {
fields.put(field.name() + "." + relationIdField.name(), relationIdField.type());
}

// get the super class of the relation class
if (currentRelationClass.superName() != null) {
currentRelationClass = index.getClassByName(currentRelationClass.superName());
} else {
currentRelationClass = null;
}
}

}

}

if (currentEntityClass.superName() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ public static class Parameter {
public String getName() {
return name;
}

public Type getType() {
return type;
}

public Object getClazz() {
return clazz;
}
}

public static class ReturnType {
Expand Down

0 comments on commit 96a7361

Please sign in to comment.