Skip to content

Commit 664e93b

Browse files
authored
Merge pull request #119 from SentryMan/matrix-dodge
Create @MatrixParam Annotation
2 parents 798ca73 + 8d85eca commit 664e93b

File tree

4 files changed

+62
-5
lines changed

4 files changed

+62
-5
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.avaje.http.api;
2+
3+
import static java.lang.annotation.ElementType.PARAMETER;
4+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5+
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.Target;
8+
9+
/** Marks a method parameter to be a matrix parameter. */
10+
@Target(value = {PARAMETER})
11+
@Retention(value = RUNTIME)
12+
public @interface MatrixParam {
13+
14+
/**
15+
* The name of the matrix parameter.
16+
*
17+
* <p>If left blank the method parameter name is used.
18+
*
19+
* <p>We typically use this when the matrix parameter uses snake-case or similar that does not map
20+
* to a valid java/kotlin parameter name.
21+
*/
22+
String value() default "";
23+
}

http-generator-core/src/main/java/io/avaje/http/generator/core/ElementReader.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class ElementReader {
2626

2727
private String paramName;
2828
private ParamType paramType;
29+
private String matrixParamName;
2930
private boolean impliedParamType;
3031
private String paramDefault;
3132

@@ -110,6 +111,15 @@ private void readAnnotations(Element element, ParamType defaultType) {
110111
this.paramDefault = null;
111112
return;
112113
}
114+
115+
MatrixParam matrixParam = element.getAnnotation(MatrixParam.class);
116+
if (matrixParam != null) {
117+
this.matrixParamName = nameFrom(matrixParam.value(), varName);
118+
this.paramType = defaultType;
119+
this.impliedParamType = true;
120+
return;
121+
}
122+
113123
if (paramType == null) {
114124
this.impliedParamType = true;
115125
if (typeHandler != null) {
@@ -235,15 +245,19 @@ private boolean setValue(Append writer, PathSegments segments, String shortType)
235245
return false;
236246
}
237247
if (impliedParamType) {
238-
PathSegments.Segment segment = segments.segment(varName);
248+
var name = matrixParamName != null ? matrixParamName : varName;
249+
PathSegments.Segment segment = segments.segment(name);
239250
if (segment != null) {
240251
// path or matrix parameter
241252
boolean requiredParam = segment.isRequired(varName);
242-
String asMethod = (typeHandler == null) ? null : (requiredParam) ? typeHandler.asMethod() : typeHandler.toMethod();
253+
String asMethod =
254+
(typeHandler == null)
255+
? null
256+
: (requiredParam) ? typeHandler.asMethod() : typeHandler.toMethod();
243257
if (asMethod != null) {
244258
writer.append(asMethod);
245259
}
246-
segment.writeGetVal(writer, varName, ctx.platform());
260+
segment.writeGetVal(writer, name, ctx.platform());
247261
if (asMethod != null) {
248262
writer.append(")");
249263
}

http-generator-core/src/main/java/io/avaje/http/generator/core/PathSegments.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.LinkedHashSet;
88
import java.util.List;
99
import java.util.Set;
10+
import java.util.regex.Pattern;
1011

1112
public class PathSegments {
1213

@@ -132,7 +133,9 @@ public boolean isEmpty() {
132133

133134
public static class Segment {
134135

136+
private static final Pattern PATTERN = Pattern.compile("[^a-zA-Z0-9_]|\\s");
135137
private final String name;
138+
private final String sanitizedName;
136139
private final String literalSection;
137140

138141
/**
@@ -150,6 +153,7 @@ public static class Segment {
150153
*/
151154
Segment(String name) {
152155
this.name = name;
156+
this.sanitizedName = PATTERN.matcher(name).replaceAll("_");
153157
this.literalSection = null;
154158
this.matrixKeys = null;
155159
this.matrixVarNames = null;
@@ -160,6 +164,7 @@ public static class Segment {
160164
*/
161165
Segment(String name, Set<String> matrixKeys) {
162166
this.name = name;
167+
this.sanitizedName = PATTERN.matcher(name).replaceAll("_");
163168
this.literalSection = null;
164169
this.matrixKeys = matrixKeys;
165170
this.matrixVarNames = new HashSet<>();
@@ -172,8 +177,10 @@ public static class Segment {
172177
* Create a literal path segment.
173178
*/
174179
public Segment(String section, boolean literalDummy) {
180+
175181
this.literalSection = section;
176182
this.name = null;
183+
this.sanitizedName = null;
177184
this.matrixKeys = null;
178185
this.matrixVarNames = null;
179186
}
@@ -219,7 +226,7 @@ void writeGetVal(Append writer, String varName, PlatformAdapter platform) {
219226
if (!hasMatrixParams()) {
220227
platform.writeReadParameter(writer, ParamType.PATHPARAM, name);
221228
} else {
222-
writer.append("%s_segment.", name);
229+
writer.append("%s_segment.", sanitizedName);
223230
if (name.equals(varName)) {
224231
writer.append("val()");
225232
} else {
@@ -238,7 +245,7 @@ private String matrixKey(String varName) {
238245

239246
public void writeCreateSegment(Append writer, PlatformAdapter platform) {
240247
writer.append(platform.indent());
241-
writer.append(" PathSegment %s_segment = PathSegment.of(", name);
248+
writer.append(" PathSegment %s_segment = PathSegment.of(", sanitizedName);
242249
platform.writeReadParameter(writer, ParamType.PATHPARAM, name + "_segment");
243250
writer.append(");").eol();
244251
}

tests/test-javalin-jsonb/src/main/java/org/example/myapp/web/test/TestController.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
import io.avaje.http.api.Post;
1414
import io.avaje.http.api.Produces;
1515
import io.avaje.http.api.Put;
16+
import io.avaje.http.api.MatrixParam;
1617
import io.javalin.http.Context;
18+
1719
@Path("test/")
1820
@Controller
1921
public class TestController {
@@ -105,4 +107,15 @@ String testForm(String name, String email, String url) {
105107
String testFormBean(MyForm form) {
106108
return form.name + "|" + form.email + "|" + form.url;
107109
}
110+
111+
@Get("/withMatrixParam/{type-1;category;vendor-34}/{range;style}")
112+
void neo(
113+
@MatrixParam("type-1") String type,
114+
String category,
115+
@MatrixParam("vendor-34") String vendor,
116+
String range,
117+
String style) {
118+
119+
System.out.println("Ever have that feeling where you're not sure if you're awake or dreaming?");
120+
}
108121
}

0 commit comments

Comments
 (0)