ice framework documentation ice doc v1.10.1
    
namespace Ice\Mvc\Route\Dispatcher;

use Ice\Mvc\Route\Dispatcher\DispatcherInterface;
use Ice\Mvc\FastRouter;

abstract class Regex implements DispatcherInterface
{
    protected staticRouteMap { set };
    protected variableRouteData { set };

    public function setData(array! data = [])
    {
        let this->staticRouteMap = data[0],
            this->variableRouteData = data[1];
    }

    protected abstract function dispatchVariableRoute(routeData, uri);

    public function dispatch(string httpMethod, string uri)
    {
        var handler, varRouteData, result, allowedMethods, uriMap, method, routeData;

        if isset this->staticRouteMap[httpMethod] && isset this->staticRouteMap[httpMethod][uri] {
            let handler = this->staticRouteMap[httpMethod][uri];
            return [FastRouter::FOUND, handler, []];
        }

        let varRouteData = this->variableRouteData;

        if isset varRouteData[httpMethod] {
            let result = this->dispatchVariableRoute(varRouteData[httpMethod], uri);

            if result[0] === FastRouter::FOUND {
                return result;
            }
        }

        // For HEAD requests, attempt fallback to GET
        if httpMethod === "HEAD" {
            if isset this->staticRouteMap["GET"][uri] {
                let handler = this->staticRouteMap["GET"][uri];

                return [FastRouter::FOUND, handler, []];
            }
            if isset varRouteData["GET"] {
                let result = this->dispatchVariableRoute(varRouteData["GET"], uri);

                if result[0] === FastRouter::FOUND {
                    return result;
                }
            }
        }

        // If nothing else matches, try fallback routes
        if isset this->staticRouteMap["*"][uri] {
            let handler = this->staticRouteMap["*"][uri];

            return [FastRouter::FOUND, handler, []];
        }
        if isset varRouteData["*"] {
            let result = this->dispatchVariableRoute(varRouteData["*"], uri);

            if result[0] === FastRouter::FOUND {
                return result;
            }
        }

        // Find allowed methods for this URI by matching against all other HTTP methods as well
        let allowedMethods = [];

        for method, uriMap in this->staticRouteMap {
            if method !== httpMethod && isset uriMap[uri] {
                let allowedMethods[] = method;
            }
        }

        for method, routeData in varRouteData {
            if method === httpMethod {
                continue;
            }

            let result = this->dispatchVariableRoute(routeData, uri);

            if result[0] === FastRouter::FOUND {
                let allowedMethods[] = method;
            }
        }
        // If there are no allowed methods the route simply does not exist
        if allowedMethods {
            return [FastRouter::METHOD_NOT_ALLOWED, allowedMethods];
        } else {
            return [FastRouter::NOT_FOUND];
        }
    }
}