Skip to content

Commit c36fa6f

Browse files
committed
#46 - ENH: Add support for request scoped @Inject for Javalin Context and Helidon ServerRequest and ServerResponse.
1 parent d934b62 commit c36fa6f

23 files changed

+682
-67
lines changed

dinject-generator/src/main/java/io/dinject/generator/Append.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
class Append {
1010

1111
private final Writer writer;
12+
private int nameIndex;
13+
private boolean comma;
1214

1315
Append(Writer writer) {
1416
this.writer = writer;
@@ -48,4 +50,21 @@ Append append(String format, Object... args) {
4850
return append(String.format(format, args));
4951
}
5052

53+
void resetNextName() {
54+
nameIndex = 0;
55+
comma = false;
56+
}
57+
58+
String nextName(String prefix) {
59+
return prefix + nameIndex++;
60+
}
61+
62+
void commaAppend(String name) {
63+
if (!comma) {
64+
comma = true;
65+
} else {
66+
append(", ");
67+
}
68+
append(name);
69+
}
5170
}

dinject-generator/src/main/java/io/dinject/generator/BeanReader.java

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class BeanReader {
5151

5252
private final Set<String> importTypes = new TreeSet<>();
5353

54+
private final BeanRequestParams requestParams;
55+
5456
private MethodReader constructor;
5557

5658
private String registrationTypes;
@@ -69,11 +71,16 @@ class BeanReader {
6971
this.type = beanType.getQualifiedName().toString();
7072
this.shortName = beanType.getSimpleName().toString();
7173
this.context = context;
74+
this.requestParams = new BeanRequestParams(type);
7275
init();
7376
}
7477

75-
private void init() {
78+
@Override
79+
public String toString() {
80+
return beanType.toString();
81+
}
7682

83+
private void init() {
7784
StringBuilder sb = new StringBuilder();
7885

7986
for (TypeMirror anInterface : beanType.getInterfaces()) {
@@ -138,7 +145,6 @@ List<FieldReader> getInjectFields() {
138145
}
139146

140147
void read(boolean factory) {
141-
142148
for (Element element : beanType.getEnclosedElements()) {
143149
ElementKind kind = element.getKind();
144150
switch (kind) {
@@ -156,6 +162,10 @@ void read(boolean factory) {
156162
constructor = findConstructor();
157163
if (constructor != null) {
158164
constructor.addImports(importTypes);
165+
constructor.checkRequest(requestParams);
166+
}
167+
for (FieldReader fields : injectFields) {
168+
fields.checkRequest(requestParams);
159169
}
160170
for (MethodReader factoryMethod : factoryMethods) {
161171
factoryMethod.addImports(importTypes);
@@ -173,7 +183,6 @@ private MethodReader findConstructor() {
173183
}
174184

175185
List<String> getDependsOn() {
176-
177186
List<String> list = new ArrayList<>();
178187
if (constructor != null) {
179188
for (MethodReader.MethodParam param : constructor.getParams()) {
@@ -346,6 +355,7 @@ private Set<String> importTypes() {
346355
if (Util.notVoid(type)) {
347356
importTypes.add(type);
348357
}
358+
requestParams.addImports(importTypes);
349359
return importTypes;
350360
}
351361

@@ -370,4 +380,49 @@ void setWrittenToFile() {
370380
this.writtenToFile = true;
371381
}
372382

383+
/**
384+
* Return true if the bean has a dependency which is a request scoped type.
385+
* Like Javalin Context, Helidon request and response types.
386+
* <p>
387+
* If request scoped then generate a BeanFactory instead.
388+
*/
389+
boolean isRequestScoped() {
390+
return requestParams.isRequestScoped();
391+
}
392+
393+
String suffix() {
394+
return isRequestScoped() ? "$factory" : "$di";
395+
}
396+
397+
/**
398+
* Add interface for this as a BeanFactory (request scoped).
399+
*/
400+
void factoryInterface(Append writer) {
401+
requestParams.factoryInterface(writer);
402+
}
403+
404+
/**
405+
* Generate the BeanFactory dependencies and create method implementation.
406+
*/
407+
void writeRequestCreate(Append writer) {
408+
if (constructor != null) {
409+
constructor.writeRequestDependency(writer);
410+
}
411+
for (FieldReader field : injectFields) {
412+
field.writeRequestDependency(writer);
413+
}
414+
requestParams.writeRequestCreate(writer);
415+
writer.resetNextName();
416+
writer.append(" %s bean = new %s(", shortName, shortName);
417+
if (constructor != null) {
418+
constructor.writeRequestConstructor(writer);
419+
}
420+
writer.append(");").eol();
421+
for (FieldReader field : injectFields) {
422+
field.writeRequestInject(writer);
423+
}
424+
writer.append(" return bean;").eol();
425+
writer.append(" }").eol();
426+
}
427+
373428
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package io.dinject.generator;
2+
3+
import java.util.Set;
4+
5+
/**
6+
* Holds detection and details of request scoped dependencies.
7+
*/
8+
class BeanRequestParams {
9+
10+
private final String parentType;
11+
12+
private RequestScope.Handler reqScopeHandler;
13+
14+
BeanRequestParams(String parentType) {
15+
this.parentType = parentType;
16+
}
17+
18+
/**
19+
* Return true if this type is a request scoped type (e.g. Javalin Context).
20+
*/
21+
boolean check(String paramType) {
22+
if (paramType != null && RequestScope.check(paramType)) {
23+
if (reqScopeHandler == null) {
24+
reqScopeHandler = RequestScope.handler(paramType);
25+
}
26+
return true;
27+
}
28+
return false;
29+
}
30+
31+
/**
32+
* Return true if the bean has request scoped dependencies.
33+
*/
34+
boolean isRequestScoped() {
35+
return reqScopeHandler != null;
36+
}
37+
38+
void factoryInterface(Append writer) {
39+
reqScopeHandler.factoryInterface(writer, nm(parentType));
40+
}
41+
42+
void addImports(Set<String> importTypes) {
43+
if (reqScopeHandler != null) {
44+
importTypes.add(Constants.SINGLETON);
45+
importTypes.add(Constants.INJECT);
46+
reqScopeHandler.addImports(importTypes);
47+
}
48+
}
49+
50+
void writeRequestCreate(Append writer) {
51+
writer.append(" @Override").eol();
52+
reqScopeHandler.writeCreateMethod(writer, nm(parentType));
53+
}
54+
55+
/**
56+
* Return the argument name based on the parameter type.
57+
*/
58+
String argumentName(String paramType) {
59+
return reqScopeHandler.argumentName(paramType);
60+
}
61+
62+
private String nm(String raw) {
63+
return Util.shortName(raw);
64+
}
65+
}

dinject-generator/src/main/java/io/dinject/generator/Constants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@ class Constants {
1212
static final String PATH = "io.dinject.controller.Path";
1313
static final String CONTROLLER = "io.dinject.controller.Controller";
1414

15+
static final String AT_SINGLETON = "@Singleton";
1516
static final String AT_GENERATED = "@Generated(\"io.dinject.generator\")";
1617
static final String META_INF_FACTORY = "META-INF/services/io.dinject.core.BeanContextFactory";
1718

19+
static final String BEAN_FACTORY = "io.dinject.core.BeanFactory";
20+
static final String BEAN_FACTORY2 = "io.dinject.core.BeanFactory2";
1821
static final String BEAN_LIFECYCLE = "io.dinject.core.BeanLifecycle";
1922
static final String BUILDER = "io.dinject.core.Builder";
23+
static final String SINGLETON = "javax.inject.Singleton";
24+
static final String INJECT = "javax.inject.Inject";
2025

2126
static final String IMPORT_CONTEXTMODULE = "import io.dinject.ContextModule;";
2227
static final String IMPORT_DEPENDENCYMETA = "import io.dinject.core.DependencyMeta;";
Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,68 @@
11
package io.dinject.generator;
22

33
import javax.lang.model.element.Element;
4-
import javax.lang.model.type.TypeMirror;
54

65
class FieldReader {
76

87
private final Element element;
9-
108
private final String name;
9+
private final UtilType type;
10+
private boolean requestParam;
11+
private String requestParamName;
1112

1213
FieldReader(Element element) {
1314
this.element = element;
1415
this.name = Util.getNamed(element);
16+
this.type = Util.determineType(element.asType());
1517
}
1618

1719
String getFieldName() {
1820
return element.getSimpleName().toString();
1921
}
2022

2123
String builderGetDependency() {
22-
23-
UtilType beanType = Util.determineType(element.asType());
24-
2524
StringBuilder sb = new StringBuilder();
26-
sb.append("b.").append(beanType.getMethod());
27-
sb.append(beanType.rawType()).append(".class");
25+
sb.append("b.").append(type.getMethod());
26+
sb.append(type.rawType()).append(".class");
2827
if (name != null) {
2928
sb.append(",\"").append(name).append("\"");
3029
}
3130
sb.append(")");
3231
return sb.toString();
3332
}
33+
34+
/**
35+
* Check for request scoped dependency.
36+
*/
37+
void checkRequest(BeanRequestParams requestParams) {
38+
requestParam = requestParams.check(type.rawType());
39+
if (requestParam) {
40+
requestParamName = requestParams.argumentName(type.rawType());
41+
}
42+
}
43+
44+
/**
45+
* Generate code for dependency inject for BeanFactory.
46+
*/
47+
void writeRequestDependency(Append writer) {
48+
if (!requestParam) {
49+
// just add as field dependency
50+
requestParamName = writer.nextName(getFieldName().toLowerCase());//"dep");
51+
final String shortType = nm(type.rawType());
52+
writer.append(" @Inject").eol();
53+
writer.append(" %s %s;", shortType, requestParamName).eol().eol();
54+
}
55+
}
56+
57+
/**
58+
* Generate code to set bean field dependencies as part of BeanFactory create().
59+
*/
60+
void writeRequestInject(Append writer) {
61+
writer.append(" bean.%s = %s;", getFieldName(), requestParamName).eol();
62+
}
63+
64+
private String nm(String raw) {
65+
return Util.shortName(raw);
66+
}
67+
3468
}

dinject-generator/src/main/java/io/dinject/generator/MethodReader.java

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ class MethodReader {
2323
private final String shortName;
2424
private final boolean isVoid;
2525
private final List<MethodParam> params = new ArrayList<>();
26-
2726
private final List<String> interfaceTypes = new ArrayList<>();
2827
private final String factoryShortName;
2928
private final boolean isFactory;
@@ -225,15 +224,42 @@ void buildLifecycleClass(Append writer) {
225224
writer.append(" }").eol().eol();
226225
}
227226

227+
/**
228+
* Check for request scoped dependency.
229+
*/
230+
void checkRequest(BeanRequestParams requestParams) {
231+
for (MethodParam param : params) {
232+
param.checkRequest(requestParams);
233+
}
234+
}
235+
236+
/**
237+
* Generate code for dependency inject for BeanFactory.
238+
*/
239+
void writeRequestDependency(Append writer) {
240+
for (MethodParam param : params) {
241+
param.writeRequestDependency(writer);
242+
}
243+
}
244+
245+
/**
246+
* Generate code constructor arguments.
247+
*/
248+
void writeRequestConstructor(Append writer) {
249+
for (MethodParam param : params) {
250+
param.writeRequestConstructor(writer);
251+
}
252+
}
228253

229254
static class MethodParam {
230255

231256
private final String named;
232257
private final UtilType utilType;
233258
private final String paramType;
234259
private final GenericType genericType;
235-
236260
private int providerIndex;
261+
private boolean requestParam;
262+
private String requestParamName;
237263

238264
MethodParam(VariableElement param) {
239265
this.named = Util.getNamed(param);
@@ -284,5 +310,30 @@ void addProviderParam(Append writer, int providerIndex) {
284310
genericType.writeShort(writer);
285311
writer.append("> prov%s", providerIndex);
286312
}
313+
314+
void checkRequest(BeanRequestParams requestParams) {
315+
requestParam = requestParams.check(paramType);
316+
if (requestParam) {
317+
requestParamName = requestParams.argumentName(paramType);
318+
}
319+
}
320+
321+
void writeRequestDependency(Append writer) {
322+
if (!requestParam) {
323+
final String shortType = nm(paramType);
324+
requestParamName = writer.nextName(shortType.toLowerCase());
325+
writer.append(" @Inject").eol();
326+
writer.append(" %s %s;", shortType, requestParamName).eol().eol();
327+
}
328+
}
329+
330+
void writeRequestConstructor(Append writer) {
331+
writer.commaAppend(requestParamName);
332+
}
333+
334+
private String nm(String raw) {
335+
return Util.shortName(raw);
336+
}
337+
287338
}
288339
}

0 commit comments

Comments
 (0)