/
StdEntityRoute.java
170 lines (146 loc) · 6.56 KB
/
StdEntityRoute.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package restx.entity;
import com.google.common.base.Optional;
import restx.RestxContext;
import restx.RestxLogLevel;
import restx.RestxRequest;
import restx.RestxRequestMatch;
import restx.RestxRequestMatcher;
import restx.RestxResponse;
import restx.RouteLifecycleListener;
import restx.StdRoute;
import restx.http.HttpStatus;
import restx.security.Permission;
import restx.security.PermissionFactory;
import java.io.IOException;
import java.lang.reflect.Type;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* User: xavierhanin
* Date: 1/19/13
* Time: 8:10 AM
*/
public abstract class StdEntityRoute<I,O> extends StdRoute {
public static class Builder<I,O> {
protected EntityRequestBodyReader<I> entityRequestBodyReader;
protected EntityResponseWriter<O> entityResponseWriter;
protected String name;
protected RestxRequestMatcher matcher;
protected HttpStatus successStatus = HttpStatus.OK;
protected RestxLogLevel logLevel = RestxLogLevel.DEFAULT;
protected PermissionFactory permissionFactory;
protected MatchedEntityRoute<I,O> matchedEntityRoute;
public Builder<I,O> entityRequestBodyReader(final EntityRequestBodyReader<I> entityRequestBodyReader) {
this.entityRequestBodyReader = entityRequestBodyReader;
return this;
}
public Builder<I,O> entityResponseWriter(final EntityResponseWriter<O> entityResponseWriter) {
this.entityResponseWriter = entityResponseWriter;
return this;
}
public Builder<I,O> name(final String name) {
this.name = name;
return this;
}
public Builder<I,O> permissionFactory(final PermissionFactory permissionFactory) {
this.permissionFactory = permissionFactory;
return this;
}
public Builder<I,O> matcher(final RestxRequestMatcher matcher) {
this.matcher = matcher;
return this;
}
public Builder<I,O> successStatus(final HttpStatus successStatus) {
this.successStatus = successStatus;
return this;
}
public Builder<I,O> logLevel(final RestxLogLevel logLevel) {
this.logLevel = logLevel;
return this;
}
public Builder<I,O> matchedEntityRoute(final MatchedEntityRoute<I, O> matchedEntityRoute) {
this.matchedEntityRoute = matchedEntityRoute;
return this;
}
public StdEntityRoute<I,O> build() {
checkNotNull(matchedEntityRoute, "you must provide a matchedEntityRoute");
return new StdEntityRoute<I, O>(
name, entityRequestBodyReader == null ? voidBodyReader() : entityRequestBodyReader,
entityResponseWriter,
matcher, successStatus, logLevel, permissionFactory) {
@Override
protected Optional<O> doRoute(RestxRequest restxRequest, RestxRequestMatch match, I i) throws IOException {
return matchedEntityRoute.route(restxRequest, match, i);
}
};
}
/*
We want to give a default value to entityRequestBodyReader to void.
It would be better to do that only if I is Void, but generics aren't reified so we can't check that.
So we need to cast it to I, without really knowing if I is Void.
*/
@SuppressWarnings("unchecked")
private EntityRequestBodyReader<I> voidBodyReader() {
return (EntityRequestBodyReader<I>) VoidContentTypeModule.VoidEntityRequestBodyReader.INSTANCE;
}
}
public static <I,O> Builder<I,O> builder() {
return new Builder<>();
}
private final EntityRequestBodyReader<I> entityRequestBodyReader;
private final EntityResponseWriter<O> entityResponseWriter;
private final RestxLogLevel logLevel;
private final PermissionFactory permissionFactory;
public StdEntityRoute(String name,
EntityRequestBodyReader<I> entityRequestBodyReader,
EntityResponseWriter<O> entityResponseWriter,
RestxRequestMatcher matcher,
HttpStatus successStatus,
RestxLogLevel logLevel,
PermissionFactory permissionFactory
) {
super(name, matcher, successStatus);
this.permissionFactory = permissionFactory;
this.entityRequestBodyReader = checkNotNull(entityRequestBodyReader);
this.entityResponseWriter = checkNotNull(entityResponseWriter);
this.logLevel = checkNotNull(logLevel);
}
/**
* The Java type of I, the entity into which request body will be unmarshalled.
*
* @return I type
*/
public Type getEntityRequestBodyType() {
return entityRequestBodyReader.getType();
}
/**
* The Java type of O, the entity from which response body will be marshalled.
*
* @return O type
*/
public Type getEntityResponseType() {
return entityResponseWriter.getType();
}
@Override
public void handle(RestxRequestMatch match, RestxRequest req, RestxResponse resp, RestxContext ctx) throws IOException {
RouteLifecycleListener lifecycleListener = ctx.getLifecycleListener();
resp.setLogLevel(logLevel);
lifecycleListener.onRouteMatch(this, req, resp);
I input = entityRequestBodyReader.readBody(req, ctx);
Optional<I> optionalInput = Optional.fromNullable(input);
lifecycleListener.onEntityInput(this, req, resp, optionalInput);
Optional<O> result = doRoute(req, match, input);
lifecycleListener.onEntityOutput(this, req, resp, optionalInput, result);
if (result.isPresent()) {
entityResponseWriter.sendResponse(getSuccessStatus(), result.get(), req, resp, ctx);
} else {
notFound(match, resp);
}
}
protected abstract Optional<O> doRoute(RestxRequest restxRequest, RestxRequestMatch match, I i) throws IOException;
// Aliases to permissionFactory allowing to have a more readable generated code through APT
protected Permission hasRole(String role){ return permissionFactory.hasRole(role); }
protected Permission anyOf(Permission... permissions){ return permissionFactory.anyOf(permissions); }
protected Permission allOf(Permission... permissions){ return permissionFactory.allOf(permissions); }
protected Permission open(){ return permissionFactory.open(); }
protected Permission isAuthenticated(){ return permissionFactory.isAuthenticated(); }
}