From 191deb079f37ec0906ec0dbf4fdd977235409d07 Mon Sep 17 00:00:00 2001 From: tursom Date: Wed, 20 May 2020 02:03:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9F=BA=E4=BA=8E=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=99=A8=E7=9A=84=E8=B7=AF=E7=94=B1=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/tursom/web/router/impl/FilterRouter.kt | 118 ++++++++++++++++++ .../web/router/impl/FilterRouterTest.kt | 10 ++ 2 files changed, 128 insertions(+) create mode 100644 web/src/main/kotlin/cn/tursom/web/router/impl/FilterRouter.kt create mode 100644 web/src/test/kotlin/cn/tursom/web/router/impl/FilterRouterTest.kt diff --git a/web/src/main/kotlin/cn/tursom/web/router/impl/FilterRouter.kt b/web/src/main/kotlin/cn/tursom/web/router/impl/FilterRouter.kt new file mode 100644 index 0000000..c32288c --- /dev/null +++ b/web/src/main/kotlin/cn/tursom/web/router/impl/FilterRouter.kt @@ -0,0 +1,118 @@ +package cn.tursom.web.router.impl + +import cn.tursom.web.router.Router +import java.util.* +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.collections.ArrayList +import kotlin.concurrent.read +import kotlin.concurrent.write + +class FilterRouter : Router { + companion object { + val flower = Regex("\\{[^{}]*\\}") + } + + private val lock = ReentrantReadWriteLock() + private val routeList = ArrayList>() + + override fun addSubRoute(route: String, value: T?, onDestroy: ((oldValue: T) -> Unit)?) = lock.write { + val matcher = DefaultMatcher(route) + val context = RouteContext(matcher.route, value, onDestroy, matcher) + routeList.add(context) + Unit + } + + override fun delRoute(route: String): Unit = lock.write { + val rRoute = route.substringBefore('?').replace(flower, "{}") + val index = routeList.indexOfFirst { it.route == rRoute } + if (index < 0) return + val (_, oldValue, onDestroy, _) = routeList[index] + routeList.removeAt(index) + oldValue?.let { onDestroy?.invoke(it) } + } + + override fun get(route: String): Pair>> = lock.read { + routeList.forEach { + val (match, param) = it.matcher.match(route) + if (match) { + return@read it.value to param + } + } + null to listOf() + } + + interface Matcher { + fun match(route: String): Pair>> + } + + data class RouteContext( + val route: String, + val value: T?, + val onDestroy: ((oldValue: T) -> Unit)?, + val matcher: Matcher + ) + + class DefaultMatcher(route: String) : Matcher { + val route: String = route.substringBefore('?').replace(flower, "{}") + private val matchList = route.split(flower).toMutableList() + private val paramList: List + + init { + matchList.add("") + val rRoute = route.substringBefore('?') + val paramList = ArrayList() + var match = '{' + var startIndex = 0 + if (startIndex >= 0) { + while (true) { + val endIndex = rRoute.indexOf(match, startIndex) + if (endIndex < 0) { + if (match == '}') { + paramList.add(rRoute.substring(startIndex)) + } + break + } + if (match == '}') { + paramList.add(rRoute.substring(startIndex, endIndex)) + } + startIndex = endIndex + 1 + match = when (match) { + '{' -> '}' + '}' -> '{' + else -> '{' + } + } + } + this.paramList = paramList + } + + override fun match(route: String): Pair>> { + val iterator = matchList.iterator() + val paramIterator = paramList.iterator() + var context = iterator.next() + if (!route.startsWith(context)) return false to listOf() + var startIndex = context.length + val paramList = LinkedList>() + while (iterator.hasNext()) { + val preContext = context + context = iterator.next() + val endIndex = route.indexOf(context, startIndex) + if (endIndex < 0) { + break + } + val paramValue = route.substring(startIndex, endIndex) + if (paramValue.contains('/')) { + break + } + if (paramIterator.hasNext()) { + paramList.add(paramIterator.next() to paramValue) + } else { + startIndex += preContext.length - 1 + break + } + startIndex = endIndex + 1 + } + return (startIndex == route.length) to paramList + } + } +} \ No newline at end of file diff --git a/web/src/test/kotlin/cn/tursom/web/router/impl/FilterRouterTest.kt b/web/src/test/kotlin/cn/tursom/web/router/impl/FilterRouterTest.kt new file mode 100644 index 0000000..f11870a --- /dev/null +++ b/web/src/test/kotlin/cn/tursom/web/router/impl/FilterRouterTest.kt @@ -0,0 +1,10 @@ +package cn.tursom.web.router.impl + +fun main() { + val router = FilterRouter() + router.addSubRoute("/123/{aa}/123","1") + router.addSubRoute("/123/{bb}/{cc}/123","2") + println(router["/123/aaa/123"]) + println(router["/123/bbb/123/123"]) + println(router["/123/bbb/ccc/123"]) +} \ No newline at end of file