laviua/komock

View on GitHub
komock-core/src/main/kotlin/ua/com/lavi/komock/http/server/handler/RoutingTable.kt

Summary

Maintainability
A
1 hr
Test Coverage
package ua.com.lavi.komock.http.server.handler

import ua.com.lavi.komock.http.handler.after.AfterResponseHandler
import ua.com.lavi.komock.http.handler.before.BeforeResponseHandler
import ua.com.lavi.komock.http.handler.callback.CallbackHandler
import ua.com.lavi.komock.http.handler.response.ResponseHandler
import ua.com.lavi.komock.model.HttpMethod
import ua.com.lavi.komock.model.Route
import java.util.*

/**
 * Created by Oleksandr Loushkin
 * Class represents routing table. It should add route. find a route by direct url or by url mask.
 */

class RoutingTable {

    private val routeMap = HashMap<String, HashMap<HttpMethod, Route>>()
    private val REGEX_URL_WILDCARD = "([A-Za-z0-9_.-~]+)"

    fun addRoute(url: String,
                 httpMethod: HttpMethod,
                 responseHandler: ResponseHandler,
                 beforeResponseHandler: BeforeResponseHandler,
                 afterResponseHandler: AfterResponseHandler,
                 callbackHandler: CallbackHandler) {
        var urlMap: HashMap<HttpMethod, Route>? = routeMap[url]
        if (urlMap == null) {
            urlMap = HashMap()
        }
        if (find(httpMethod, url) != null) {
            throw RuntimeException("Route with httpMethod: ${httpMethod.name} and requestedUrl: $url is already exists in the routing table")
        }
        urlMap[httpMethod] = Route(url, responseHandler, beforeResponseHandler, afterResponseHandler, callbackHandler)
        routeMap[url] = urlMap
    }

    fun find(httpMethod: HttpMethod, requestedUrl: String): Route? {
        val httpMethodsMap = routeMap[requestedUrl]
        if (httpMethodsMap == null) {
            for (routeKey in routeMap.keys) {
                if (routeKey == "/**") {
                    return routeMap[routeKey]?.get(httpMethod)
                }
                val pattern = routeKey.replace("*", REGEX_URL_WILDCARD)
                if (Regex(pattern).matchEntire(requestedUrl) != null) {
                    return routeMap[routeKey]!![httpMethod]
                }
            }
            return null
        } else {
            return httpMethodsMap[httpMethod]
        }
    }

    fun clearRoutes() {
        routeMap.clear()
    }

    fun getFullRouteMap(): Map<String, MutableMap<HttpMethod, Route>> {
        return routeMap
    }

    fun deleteRoute(url: String, httpMethod: HttpMethod) {
        routeMap[url]?.remove(httpMethod)
        if (routeMap[url]?.size == 0) {
            routeMap.remove(url)
        }
    }
}