diff --git a/git b/git
new file mode 100644
index 0000000..e69de29
diff --git a/jax-rs-linker-integration-tests/no-configuration-webapp/src/test/java/fr/vidal/oss/jax_rs_linker/it/BrandResourceLinkerTest.java b/jax-rs-linker-integration-tests/no-configuration-webapp/src/test/java/fr/vidal/oss/jax_rs_linker/it/BrandResourceLinkerTest.java
new file mode 100644
index 0000000..bb06c6d
--- /dev/null
+++ b/jax-rs-linker-integration-tests/no-configuration-webapp/src/test/java/fr/vidal/oss/jax_rs_linker/it/BrandResourceLinkerTest.java
@@ -0,0 +1,27 @@
+package fr.vidal.oss.jax_rs_linker.it;
+
+import fr.vidal.oss.jax_rs_linker.Linkers;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class BrandResourceLinkerTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void no_exception_is_thrown_when_argument_matches_regex() {
+ Linkers.brandResourceLinker()
+ .relatedBrandResourceByZipCode()
+ .replace(BrandResourcePathParameters.CODE, "aBc");
+ }
+
+ @Test
+ public void illegal_argument_exception_is_thrown_when_regex_is_not_matched() {
+ thrown.expect(IllegalArgumentException.class);
+ Linkers.brandResourceLinker()
+ .relatedBrandResourceByZipCode()
+ .replace(BrandResourcePathParameters.CODE, "aBD2");
+ }
+}
diff --git a/jax-rs-linker/pom.xml b/jax-rs-linker/pom.xml
index e1a08f3..85c053d 100644
--- a/jax-rs-linker/pom.xml
+++ b/jax-rs-linker/pom.xml
@@ -84,6 +84,11 @@
com.google
hidden.com.google
+
+ com.google.common.base.Optional
+ com.google.common.base.Present
+ com.google.common.base.Absent
+
true
diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/NoPathParameters.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/NoPathParameters.java
index 00e97ee..028ec31 100644
--- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/NoPathParameters.java
+++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/NoPathParameters.java
@@ -1,5 +1,9 @@
package fr.vidal.oss.jax_rs_linker.api;
+import com.google.common.base.Optional;
+
+import java.util.regex.Pattern;
+
public enum NoPathParameters implements PathParameters {
;
@@ -7,4 +11,9 @@ public enum NoPathParameters implements PathParameters {
public String placeholder() {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public Optional regex() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/PathParameters.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/PathParameters.java
index cfc0871..c829aa0 100644
--- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/PathParameters.java
+++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/api/PathParameters.java
@@ -1,5 +1,10 @@
package fr.vidal.oss.jax_rs_linker.api;
+import com.google.common.base.Optional;
+
+import java.util.regex.Pattern;
+
public interface PathParameters {
String placeholder();
+ Optional regex();
}
diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/ApiPath.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/ApiPath.java
index 06efecd..a93693a 100644
--- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/ApiPath.java
+++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/ApiPath.java
@@ -6,6 +6,7 @@
import java.util.Collection;
+import static fr.vidal.oss.jax_rs_linker.parser.ApiPaths.decorate;
import static fr.vidal.oss.jax_rs_linker.parser.ApiPaths.sanitize;
public class ApiPath {
@@ -15,7 +16,7 @@ public class ApiPath {
public ApiPath(String path, Collection pathParameters) {
this.path = sanitize(path);
- this.pathParameters = pathParameters;
+ this.pathParameters = decorate(pathParameters, path);
}
public String getPath() {
diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/PathParameter.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/PathParameter.java
index 6b395a9..3b0aa0c 100644
--- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/PathParameter.java
+++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/PathParameter.java
@@ -1,19 +1,38 @@
package fr.vidal.oss.jax_rs_linker.model;
-import com.google.common.base.Objects;
+import com.google.common.base.*;
+import java.util.regex.Pattern;
+
+import static com.google.common.base.Optional.absent;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
public class PathParameter {
private final ClassName type;
private final String name;
+ private final Optional regex;
public PathParameter(ClassName type, String name) {
+ this(type, name, Optional.absent());
+ }
+
+ public PathParameter(ClassName type, String name, String regex) {
+ this.type = type;
+ this.name = name;
+ this.regex = Optional.of(Pattern.compile(regex));
+ }
+
+ private PathParameter(ClassName type, String name, Optional regex) {
this.type = type;
this.name = name;
+ this.regex = regex;
}
+
+
public ClassName getType() {
return type;
}
@@ -22,6 +41,11 @@ public String getName() {
return name;
}
+ public Optional getRegex() {
+ return regex;
+ }
+
+
@Override
public int hashCode() {
return Objects.hashCode(type, name);
diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrl.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrl.java
index 7e59822..d702c43 100644
--- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrl.java
+++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrl.java
@@ -1,6 +1,7 @@
package fr.vidal.oss.jax_rs_linker.model;
import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -12,6 +13,7 @@
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.not;
@@ -41,6 +43,7 @@ private TemplatedUrl(String path, Collection pathParameters, Map<
public TemplatedUrl replace(T parameter, String value) {
checkState(!pathParameters.isEmpty(), "No more path parameters to replace");
+ validateParamValue(parameter.regex(), value);
return new TemplatedUrl<>(
path.replace(placeholder(parameter.placeholder()), value),
@@ -61,6 +64,14 @@ public String value() {
return path + TO_QUERY_STRING.apply(queryParameters);
}
+ private void validateParamValue(Optional regex, String value) {
+ if (regex.isPresent()) {
+ if (!regex.get().matcher(value).matches()) {
+ throw new IllegalArgumentException(String.format("The given value doesn't match the parameter regex: %s", regex.get()));
+ }
+ }
+ }
+
private String parameterNames() {
return FluentIterable.from(pathParameters)
.transform(PathParameterToName.TO_NAME)
diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ApiPaths.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ApiPaths.java
index b09515f..7851921 100644
--- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ApiPaths.java
+++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ApiPaths.java
@@ -1,5 +1,20 @@
package fr.vidal.oss.jax_rs_linker.parser;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import fr.vidal.oss.jax_rs_linker.model.PathParameter;
+
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import static com.google.common.base.Optional.absent;
+import static com.google.common.base.Optional.of;
+import static com.google.common.collect.Maps.newHashMap;
+
public final class ApiPaths {
public static String sanitize(String path) {
@@ -12,4 +27,41 @@ public static String sanitize(String path) {
return path.substring(0, colonPosition).trim()
+ sanitize(path.substring(closingBracePosition));
}
+
+ public static Collection decorate(Collection pathParameters, String path) {
+ final Map parametersRegex = extractParametersRegex(path);
+
+ return FluentIterable.from(pathParameters).transform(new Function() {
+ @Nullable
+ @Override
+ public PathParameter apply(PathParameter pathParameter) {
+ if (parametersRegex.containsKey(pathParameter.getName())) {
+ return new PathParameter(pathParameter.getType(),
+ pathParameter.getName(),
+ parametersRegex.get(pathParameter.getName())
+ );
+ }
+ return pathParameter;
+ }
+ }).toList();
+ }
+
+ private static Map extractParametersRegex(String path) {
+ Map parameterAndRegex = newHashMap();
+
+ StringTokenizer st = new StringTokenizer(path, "/");
+ while (st.hasMoreTokens()) {
+ String pathParam = st.nextToken();
+ if (pathParam.contains("{")) {
+ int colonPosition = pathParam.indexOf(':');
+ if (colonPosition != -1) {
+ String name = pathParam.substring(1, colonPosition).trim();
+ String regex = pathParam.substring(colonPosition + 1, pathParam.length() - 1).trim();
+ parameterAndRegex.put(name, regex);
+ }
+ }
+
+ }
+ return parameterAndRegex;
+ }
}
diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/PathParamsEnumWriter.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/PathParamsEnumWriter.java
index 2680dc6..212c745 100644
--- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/PathParamsEnumWriter.java
+++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/PathParamsEnumWriter.java
@@ -1,10 +1,8 @@
package fr.vidal.oss.jax_rs_linker.writer;
+import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.*;
import fr.vidal.oss.jax_rs_linker.LinkerAnnotationProcessor;
import fr.vidal.oss.jax_rs_linker.api.PathParameters;
import fr.vidal.oss.jax_rs_linker.functions.MappingToPathParameters;
@@ -17,6 +15,7 @@
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
+import java.util.regex.Pattern;
import static javax.lang.model.element.Modifier.*;
@@ -40,17 +39,33 @@ public void write(ClassName generatedClass, Collection mappings) throws
writeEnumeration(mappings, typeBuilder);
+ TypeName optionalOfString =
+ ParameterizedTypeName.get(
+ com.squareup.javapoet.ClassName.get(Optional.class),
+ com.squareup.javapoet.ClassName.get(Pattern.class)
+ );
+
typeBuilder.addField(String.class, "placeholder", PRIVATE, FINAL)
- .addMethod(MethodSpec.constructorBuilder()
- .addParameter(String.class, "placeholder")
- .addCode("this.$L = $L;\n", "placeholder", "placeholder")
- .build())
- .addMethod(MethodSpec.methodBuilder("placeholder")
- .addAnnotation(Override.class)
- .addModifiers(PUBLIC, FINAL)
- .returns(String.class)
- .addCode("return this.$L;\n", "placeholder")
- .build());
+ .addField(optionalOfString, "regex", PRIVATE, FINAL)
+ .addMethod(MethodSpec.constructorBuilder()
+ .addParameter(String.class, "placeholder")
+ .addParameter(optionalOfString, "regex")
+ .addCode("this.$L = $L;\n", "placeholder", "placeholder")
+ .addCode("this.$L = $L;\n", "regex", "regex")
+ .build())
+ .addMethod(MethodSpec.methodBuilder("placeholder")
+ .addAnnotation(Override.class)
+ .addModifiers(PUBLIC, FINAL)
+ .returns(String.class)
+ .addCode("return this.$L;\n", "placeholder")
+ .build())
+ .addMethod(MethodSpec.methodBuilder("regex")
+ .addAnnotation(Override.class)
+ .addModifiers(PUBLIC, FINAL)
+ .returns(optionalOfString)
+ .addCode("return this.$L;\n", "regex")
+ .build());
+ ;
JavaFile.builder(generatedClass.packageName(), typeBuilder.build())
@@ -62,10 +77,21 @@ public void write(ClassName generatedClass, Collection mappings) throws
private void writeEnumeration(Collection mappings, TypeSpec.Builder typeBuilder) throws IOException {
for (PathParameter parameter : enumConstants(mappings)) {
- typeBuilder.addEnumConstant(
- EnumConstants.constantName(parameter.getName()),
- TypeSpec.anonymousClassBuilder("$S", parameter.getName()).build()
- );
+ Optional regex = parameter.getRegex();
+ String name = parameter.getName();
+ if (regex.isPresent()) {
+ typeBuilder.addEnumConstant(
+ EnumConstants.constantName(name),
+ TypeSpec.anonymousClassBuilder("$S, Optional.of(Pattern.compile($S))", name, regex.get())
+ .build()
+ );
+ } else {
+ typeBuilder.addEnumConstant(
+ EnumConstants.constantName(name),
+ TypeSpec.anonymousClassBuilder("$S, Optional.absent()", name)
+ .build()
+ );
+ }
}
}
diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrlTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrlTest.java
index 2bc1f7c..eae456d 100644
--- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrlTest.java
+++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/TemplatedUrlTest.java
@@ -1,5 +1,6 @@
package fr.vidal.oss.jax_rs_linker.model;
+import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import fr.vidal.oss.jax_rs_linker.api.NoQueryParameters;
import fr.vidal.oss.jax_rs_linker.api.PathParameters;
@@ -8,6 +9,7 @@
import org.junit.rules.ExpectedException;
import java.util.Collection;
+import java.util.regex.Pattern;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
@@ -67,12 +69,16 @@ private ClassName className(String type) {
}
}
-enum ProductParameters implements PathParameters
-{
+enum ProductParameters implements PathParameters {
ID;
@Override
public String placeholder() {
return "id";
}
+
+ @Override
+ public Optional regex() {
+ return Optional.absent();
+ }
}
diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ApiPathsTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ApiPathsTest.java
index cebbfbc..743475a 100644
--- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ApiPathsTest.java
+++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ApiPathsTest.java
@@ -1,7 +1,18 @@
package fr.vidal.oss.jax_rs_linker.parser;
+import com.google.common.base.Optional;
+import fr.vidal.oss.jax_rs_linker.model.ClassName;
+import fr.vidal.oss.jax_rs_linker.model.PathParameter;
+import org.assertj.core.api.iterable.Extractor;
import org.junit.Test;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import static com.google.common.collect.Sets.newHashSet;
+import static fr.vidal.oss.jax_rs_linker.parser.ApiPaths.decorate;
import static fr.vidal.oss.jax_rs_linker.parser.ApiPaths.sanitize;
import static org.assertj.core.api.Assertions.assertThat;
@@ -42,4 +53,70 @@ public void keeps_regexless_parameterized_paths_untouched() {
assertThat(sanitize("/api/boring/{parameterized}/path"))
.isEqualTo("/api/boring/{parameterized}/path");
}
+
+ @Test
+ public void adds_regex_to_path_parameters() {
+ Set pathParameters = newHashSet(new PathParameter(ClassName.valueOf(String.class.getName()), "param"));
+ Collection result = decorate(pathParameters, "/api/boring/{param:([a-zA-Z0-9])+}");
+
+ assertThat(result).extracting(patternToOptionalOfString())
+ .containsExactly(Optional.of("([a-zA-Z0-9])+"));
+ }
+
+ @Test
+ public void adds_correct_regex_to_multiple_path_parameters() {
+ Set pathParameters = newHashSet(
+ new PathParameter(ClassName.valueOf(String.class.getName()), "param"),
+ new PathParameter(ClassName.valueOf(String.class.getName()), "other")
+ );
+ Collection result = decorate(pathParameters,
+ "/api/boring/{param:([a-zA-Z0-9])+}/{other:[1-9]}");
+
+ assertThat(result).extracting(patternToOptionalOfString())
+ .contains(Optional.of("([a-zA-Z0-9])+"), Optional.of("[1-9]"));
+ }
+
+ @Test
+ public void keeps_regexless_path_parameters_untouched() {
+ Set pathParameters = newHashSet(new PathParameter(ClassName.valueOf(String.class.getName()), "param"));
+ Collection result = decorate(pathParameters, "/api/boring/{param}");
+
+ assertThat(result).extracting(patternToOptionalOfString()).containsExactly(Optional.absent());
+ }
+
+ @Test
+ public void keeps_regexless_multiple_path_parameters_untouched() {
+ Set pathParameters = newHashSet(
+ new PathParameter(ClassName.valueOf(String.class.getName()), "param"),
+ new PathParameter(ClassName.valueOf(String.class.getName()), "other")
+ );
+ Collection result = decorate(pathParameters, "/api/boring/{param}/{other}");
+
+ assertThat(result).extracting(patternToOptionalOfString())
+ .containsExactly(Optional.absent(), Optional.absent());
+ }
+
+ @Test
+ public void adds_regex_to_corresponding_path_parameter_and_keeps_regexless_path_parameter_untouched() {
+ Set pathParameters = newHashSet(
+ new PathParameter(ClassName.valueOf(String.class.getName()), "param"),
+ new PathParameter(ClassName.valueOf(String.class.getName()), "other"),
+ new PathParameter(ClassName.valueOf(String.class.getName()), "last")
+ );
+ Collection result = decorate(pathParameters, "/api/boring/{param}/{other:[1-9]}/{last}");
+
+ assertThat(result).extracting(patternToOptionalOfString())
+ .contains(Optional.absent(), Optional.of("[1-9]"), Optional.absent());
+ }
+
+ private Extractor> patternToOptionalOfString() {
+ return new Extractor>() {
+ @Override
+ public Optional extract(PathParameter pathParameter) {
+ return pathParameter.getRegex().isPresent()?
+ Optional.of(pathParameter.getRegex().get().pattern()):
+ Optional.absent();
+ }
+ };
+ }
}
diff --git a/jax-rs-linker/src/test/resources/BrandResourcePathParameters.java b/jax-rs-linker/src/test/resources/BrandResourcePathParameters.java
index c5192bb..ac46c1c 100644
--- a/jax-rs-linker/src/test/resources/BrandResourcePathParameters.java
+++ b/jax-rs-linker/src/test/resources/BrandResourcePathParameters.java
@@ -1,27 +1,37 @@
package fr.vidal.oss.jax_rs_linker.parser;
+import com.google.common.base.Optional;
import fr.vidal.oss.jax_rs_linker.api.PathParameters;
import java.lang.Override;
import java.lang.String;
+import java.util.regex.Pattern;
import javax.annotation.Generated;
@Generated("fr.vidal.oss.jax_rs_linker.LinkerAnnotationProcessor")
public enum BrandResourcePathParameters implements PathParameters {
- CODE("code"),
+ CODE("code", Optional.absent()),
- ID("id"),
+ ID("id", Optional.absent()),
- ZIP("zip");
+ ZIP("zip", Optional.absent());
private final String placeholder;
- BrandResourcePathParameters(String placeholder) {
+ private final Optional regex;
+
+ BrandResourcePathParameters(String placeholder, Optional regex) {
this.placeholder = placeholder;
+ this.regex = regex;
}
@Override
public final String placeholder() {
return this.placeholder;
}
+
+ @Override
+ public final Optional regex() {
+ return this.regex;
+ }
}
diff --git a/jax-rs-linker/src/test/resources/PersonResourcePathParameters.java b/jax-rs-linker/src/test/resources/PersonResourcePathParameters.java
index 3d9f5f7..9286cad 100644
--- a/jax-rs-linker/src/test/resources/PersonResourcePathParameters.java
+++ b/jax-rs-linker/src/test/resources/PersonResourcePathParameters.java
@@ -1,25 +1,34 @@
package fr.vidal.oss.jax_rs_linker.parser;
+import com.google.common.base.Optional;
import fr.vidal.oss.jax_rs_linker.api.PathParameters;
import java.lang.Override;
import java.lang.String;
+import java.util.regex.Pattern;
import javax.annotation.Generated;
@Generated("fr.vidal.oss.jax_rs_linker.LinkerAnnotationProcessor")
public enum PersonResourcePathParameters implements PathParameters {
- FIRST_NAME("firstName"),
+ FIRST_NAME("firstName", Optional.of(Pattern.compile(".*"))),
- ID("id");
+ ID("id", Optional.absent());
private final String placeholder;
+ private final Optional regex;
- PersonResourcePathParameters(String placeholder) {
+ PersonResourcePathParameters(String placeholder, Optional regex) {
this.placeholder = placeholder;
+ this.regex = regex;
}
@Override
public final String placeholder() {
return this.placeholder;
}
+
+ @Override
+ public final Optional regex() {
+ return this.regex;
+ }
}
diff --git a/jax-rs-linker/src/test/resources/ProductResourcePathParameters.java b/jax-rs-linker/src/test/resources/ProductResourcePathParameters.java
index 767811c..fdee8c1 100644
--- a/jax-rs-linker/src/test/resources/ProductResourcePathParameters.java
+++ b/jax-rs-linker/src/test/resources/ProductResourcePathParameters.java
@@ -1,23 +1,33 @@
package fr.vidal.oss.jax_rs_linker.parser;
+import com.google.common.base.Optional;
import fr.vidal.oss.jax_rs_linker.api.PathParameters;
import java.lang.Override;
import java.lang.String;
+import java.util.regex.Pattern;
import javax.annotation.Generated;
@Generated("fr.vidal.oss.jax_rs_linker.LinkerAnnotationProcessor")
public enum ProductResourcePathParameters implements PathParameters {
- ID("id");
+ ID("id", Optional.absent());
private final String placeholder;
- ProductResourcePathParameters(String placeholder) {
+ private final Optional regex;
+
+ ProductResourcePathParameters(String placeholder, Optional regex) {
this.placeholder = placeholder;
+ this.regex = regex;
}
@Override
public final String placeholder() {
return this.placeholder;
}
+
+ @Override
+ public final Optional regex() {
+ return this.regex;
+ }
}