forked from quarkusio/quarkus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DeleteMethodImplementor.java
142 lines (123 loc) · 6.19 KB
/
DeleteMethodImplementor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package io.quarkus.rest.data.panache.deployment.methods;
import static io.quarkus.gizmo.MethodDescriptor.ofMethod;
import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.ofType;
import javax.ws.rs.core.Response;
import io.quarkus.gizmo.BranchResult;
import io.quarkus.gizmo.ClassCreator;
import io.quarkus.gizmo.FieldDescriptor;
import io.quarkus.gizmo.MethodCreator;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.gizmo.TryBlock;
import io.quarkus.rest.data.panache.RestDataResource;
import io.quarkus.rest.data.panache.deployment.ResourceMetadata;
import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties;
import io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator;
import io.quarkus.rest.data.panache.deployment.utils.UniImplementor;
import io.smallrye.mutiny.Uni;
public final class DeleteMethodImplementor extends StandardMethodImplementor {
private static final String METHOD_NAME = "delete";
private static final String RESOURCE_METHOD_NAME = "delete";
private static final String EXCEPTION_MESSAGE = "Failed to delete an entity";
private static final String REL = "remove";
public DeleteMethodImplementor(boolean isResteasyClassic, boolean isReactivePanache) {
super(isResteasyClassic, isReactivePanache);
}
/**
* Generate JAX-RS DELETE method.
*
* The RESTEasy Classic version exposes {@link RestDataResource#delete(Object)}
* and the generated code looks more or less like this:
*
* <pre>
* {@code
* @DELETE
* @Path("{id}")
* @LinkResource(
* rel = "remove",
* entityClassName = "com.example.Entity"
* )
* public Response delete(@PathParam("id") ID id) throws RestDataPanacheException {
* try {
* boolean deleted = restDataResource.delete(id);
* if (deleted) {
* return Response.noContent().build();
* } else {
* return Response.status(404).build();
* }
* } catch (Throwable t) {
* throw new RestDataPanacheException(t);
* }
* }
* }
* </pre>
*
* The RESTEasy Reactive version exposes {@link io.quarkus.rest.data.panache.ReactiveRestDataResource#delete(Object)}
* and the generated code looks more or less like this:
*
* <pre>
* {@code
* @DELETE
* @Path("{id}")
* @LinkResource(
* rel = "remove",
* entityClassName = "com.example.Entity"
* )
* public Uni<Response> delete(@PathParam("id") ID id) throws RestDataPanacheException {
* try {
* return restDataResource.delete(id).map(deleted -> deleted ? Response.noContent().build() : Response.status(404).build());
* } catch (Throwable t) {
* throw new RestDataPanacheException(t);
* }
* }
* }
* </pre>
*/
@Override
protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata,
ResourceProperties resourceProperties, FieldDescriptor resourceField) {
MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator,
isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()),
resourceMetadata.getIdType());
// Add method annotations
addPathAnnotation(methodCreator, appendToPath(resourceProperties.getPath(RESOURCE_METHOD_NAME), "{id}"));
addDeleteAnnotation(methodCreator);
addPathParamAnnotation(methodCreator.getParameterAnnotations(0), "id");
addLinksAnnotation(methodCreator, resourceMetadata.getEntityType(), REL);
ResultHandle resource = methodCreator.readInstanceField(resourceField, methodCreator.getThis());
ResultHandle id = methodCreator.getMethodParam(0);
if (isNotReactivePanache()) {
TryBlock tryBlock = implementTryBlock(methodCreator, EXCEPTION_MESSAGE);
ResultHandle deleted = tryBlock.invokeVirtualMethod(
ofMethod(resourceMetadata.getResourceClass(), RESOURCE_METHOD_NAME, boolean.class, Object.class),
resource, id);
// Return response
BranchResult entityWasDeleted = tryBlock.ifNonZero(deleted);
entityWasDeleted.trueBranch().returnValue(responseImplementor.noContent(entityWasDeleted.trueBranch()));
entityWasDeleted.falseBranch().returnValue(responseImplementor.notFound(entityWasDeleted.falseBranch()));
tryBlock.close();
} else {
ResultHandle uniDeleted = methodCreator.invokeVirtualMethod(
ofMethod(resourceMetadata.getResourceClass(), RESOURCE_METHOD_NAME, Uni.class, Object.class),
resource, id);
methodCreator.returnValue(UniImplementor.map(methodCreator, uniDeleted, EXCEPTION_MESSAGE,
(body, entity) -> {
ResultHandle deleted = body.checkCast(entity, Boolean.class);
// Workaround to have boolean type, otherwise it's an integer.
ResultHandle falseDefault = body.invokeStaticMethod(
ofMethod(Boolean.class, "valueOf", Boolean.class, String.class), body.load("false"));
ResultHandle deletedAsInt = body.invokeVirtualMethod(
ofMethod(Boolean.class, "compareTo", int.class, Boolean.class), deleted, falseDefault);
BranchResult entityWasDeleted = body.ifNonZero(deletedAsInt);
entityWasDeleted.trueBranch()
.returnValue(responseImplementor.noContent(entityWasDeleted.trueBranch()));
entityWasDeleted.falseBranch()
.returnValue(responseImplementor.notFound(entityWasDeleted.falseBranch()));
}));
}
methodCreator.close();
}
@Override
protected String getResourceMethodName() {
return RESOURCE_METHOD_NAME;
}
}