class TrieRouter {
        private final Node root;

        public TrieRouter() {
            this.root = new Node();
            this.root.path = "/";
            this.root.segment = "/";
        }

        // add route
        public TrieRouter addRoute(String path) {
            if (StringKit.isEmpty(path)) {
                return this;
            }
            String strippedPath = StringKit.strip(path, "/");
            String[] strings = strippedPath.split("/");
            if (strings.length != 0) {
                Node node = root;
                // split by /
                for (String segment : strings) {
                    node = addNode(node, segment);
                    if ("**".equals(segment)) {
                        break;
                    }
                }
                // At the end, set the path of the child node
                node.path = path;
            }
            return this;
        }

        // add note
        private Node addNode(Node node, String segment) {<FILL_FUNCTION_BODY>}

        // match route
        public String matchRoute(String path) {
            if (StringKit.isEmpty(path)) {
                return null;
            }
            String strippedPath = StringKit.strip(path, "/");
            String[] strings = strippedPath.split("/");
            if (strings.length != 0) {
                Node node = root;
                // split by /
                for (String segment : strings) {
                    node = matchNode(node, segment);
                    // if no route is matched or a wildcard route is used, break:
                    if (node == null || node.isWildcard) {
                        break;
                    }
                }
                if (node != null) {
                    return node.path;
                }
            }
            return null;
        }

        public boolean match(String path) {
            return matchRoute(path) != null;
        }

        // match child node
        private Node matchNode(Node node, String segment) {
            if (node.staticRouters != null && node.staticRouters.containsKey(segment)) {
                return node.staticRouters.get(segment);
            }
            if (node.dynamicRouter != null)
                return node.dynamicRouter;
            if (node.isWildcard)
                return node;
            return null;
        }
    }

            // If it is a wildcard node, return the current node directly:
            if ("**".equals(segment)) {
                node.isWildcard = true;
                return node;
            }
            // if it is a dynamic route,
            // create a child node and then hang the child node under the current node:
            if (segment.startsWith(":")) {
                Node childNode = new Node();
                childNode.segment = segment;
                node.dynamicRouter = childNode;
                return childNode;
            }

            Node childNode;
            // Static route, put in a Map,
            // the key of the Map is the URL segment, value is the new child node:
            if (node.staticRouters == null) {
                node.staticRouters = new HashMap<>();
            }
            if (node.staticRouters.containsKey(segment)) {
                childNode = node.staticRouters.get(segment);
            } else {
                childNode = new Node();
                childNode.segment = segment;
                node.dynamicRouter = childNode;
                node.staticRouters.put(segment, childNode);
            }
            return childNode;
        
<no_super_class>