Create base UriTemplate
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
package com.bartlomiejpluta.ttsserver.core.web.exception
|
||||||
|
|
||||||
|
class UriTemplateException(message: String, val position: Int) : Exception(message)
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.bartlomiejpluta.ttsserver.core.web.uri
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.ttsserver.core.web.exception.UriTemplateException
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
class UriTemplate private constructor(uri: String) {
|
||||||
|
private val variables = mutableListOf<String>()
|
||||||
|
private var pattern: Pattern
|
||||||
|
|
||||||
|
init {
|
||||||
|
val patternBuilder = StringBuilder()
|
||||||
|
var variableBuilder: StringBuilder? = null
|
||||||
|
var isVariable = false
|
||||||
|
|
||||||
|
uri.forEachIndexed { index, char ->
|
||||||
|
when {
|
||||||
|
char == '{' -> {
|
||||||
|
if (isVariable) {
|
||||||
|
error("Templates cannot be nested", index + 1)
|
||||||
|
}
|
||||||
|
isVariable = true
|
||||||
|
variableBuilder = StringBuilder()
|
||||||
|
patternBuilder.append("(\\w+)")
|
||||||
|
}
|
||||||
|
|
||||||
|
char == '}' -> {
|
||||||
|
isVariable = false
|
||||||
|
variables.add(variableBuilder.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
isVariable -> char.takeIf { it.isLetter() } ?: error(
|
||||||
|
"Only letters are allowed as template",
|
||||||
|
index + 1
|
||||||
|
).let { variableBuilder?.append(it) }
|
||||||
|
|
||||||
|
else -> patternBuilder.append(char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVariable) {
|
||||||
|
error("Unclosed template found", patternBuilder.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern = Pattern.compile("^${patternBuilder.toString()}\$")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun error(message: String, position: Int): Unit =
|
||||||
|
throw UriTemplateException(message, position)
|
||||||
|
|
||||||
|
|
||||||
|
fun match(url: String): MatchingResult {
|
||||||
|
val matcher = pattern.matcher(url)
|
||||||
|
|
||||||
|
if (matcher.find()) {
|
||||||
|
val matchedVariables = IntRange(0, matcher.groupCount() - 1)
|
||||||
|
.map { variables[it] to matcher.group(it + 1)!! }
|
||||||
|
.toMap()
|
||||||
|
|
||||||
|
return MatchingResult(true, matchedVariables)
|
||||||
|
}
|
||||||
|
|
||||||
|
return MatchingResult(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MatchingResult(val matched: Boolean, val variables: Map<String, String> = emptyMap())
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun parse(uriTemplate: String): UriTemplate {
|
||||||
|
return UriTemplate(uriTemplate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user