private Object _invoke()

in grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/DefaultUrlMappingEvaluator.java [586:733]


        private Object _invoke(String methodName, Object arg, Object delegate) {
            try {
                var mappingInfo = pushNewMetaMappingInfo();
                var currentConstraints = mappingInfo.getConstraints();
                var args = (Object[]) arg;
                var mappedURI = establishFullURI(methodName);
                var isResponseCode = isResponseCode(mappedURI);
                if (mappedURI.startsWith(SLASH) || isResponseCode) {
                    // Create a new parameter map for this mapping.
                    parameterValues = new HashMap<>();
                    Map<?,?> variables = binding != null ? binding.getVariables() : null;
                    boolean hasParent = !parentResources.isEmpty();
                    try {
                        if (!hasParent) {
                            urlDefiningMode = false;
                        }
                        args = args != null && args.length > 0 ? args : new Object[] {Collections.emptyMap()};
                        if (args[0] instanceof Closure<?>) {
                            UrlMappingData urlData = createUrlMappingData(mappedURI, isResponseCode);

                            Closure<?> callable = (Closure<?>) args[0];

                            if (delegate != null) {
                                callable.setDelegate(delegate);
                            }
                            callable.call();

                            if (binding != null) {
                                mappingInfo.setController(variables.get(CONTROLLER));
                                mappingInfo.setAction(variables.get(ACTION));
                                mappingInfo.setView(variables.get(VIEW));
                                mappingInfo.setUri(variables.get(UrlMapping.URI));
                                mappingInfo.setPlugin(variables.get(PLUGIN));
                                mappingInfo.setNamespace(variables.get(NAMESPACE));
                                if (variables.containsKey(HTTP_METHOD)) {
                                    mappingInfo.setHttpMethod(variables.get(HTTP_METHOD).toString());
                                }
                            }

                            var constraints = currentConstraints.toArray(new ConstrainedProperty[0]);
                            UrlMapping urlMapping;
                            if (mappingInfo.getUri() != null) {
                                try {
                                    urlMapping = new RegexUrlMapping(urlData, new URI(mappingInfo.getUri().toString()), constraints, grailsApplication);
                                } catch (URISyntaxException e) {
                                    throw new UrlMappingException("Cannot map to invalid URI: " + e.getMessage(), e);
                                }
                            } else {
                                urlMapping = createURLMapping(urlData, isResponseCode, mappingInfo.getRedirectInfo(), mappingInfo.getController(), mappingInfo.getAction(), mappingInfo.getNamespace(), mappingInfo.getPlugin(), mappingInfo.getView(), mappingInfo.getHttpMethod(), null, constraints);
                            }

                            if (binding != null) {
                                Object parse = getParseRequest(Collections.emptyMap(), variables);
                                if (parse instanceof Boolean) {
                                    urlMapping.setParseRequest((Boolean) parse);
                                }
                            }
                            configureUrlMapping(urlMapping);
                            return urlMapping;
                        }

                        if (args[0] instanceof Map) {
                            Map<?,?> namedArguments = (Map<?,?>) args[0];
                            String version = null;

                            if (namedArguments.containsKey(UrlMapping.VERSION)) {
                                version = namedArguments.get(UrlMapping.VERSION).toString();
                            }
                            if (namedArguments.containsKey(NAMESPACE)) {
                                mappingInfo.setNamespace(namedArguments.get(NAMESPACE).toString());
                            }
                            if (namedArguments.containsKey(PLUGIN)) {
                                mappingInfo.setPlugin(namedArguments.get(PLUGIN).toString());
                            }

                            var urlData = createUrlMappingData(mappedURI, isResponseCode);

                            if (namedArguments.containsKey(RESOURCE) || namedArguments.containsKey(SINGLE)) {
                                Object controller;
                                if (namedArguments.containsKey(RESOURCE)) {
                                    GrailsUtil.deprecated("The " + RESOURCE + " syntax is deprecated and will be removed in a future release. Use " + SINGLE + " instead.");
                                    controller = namedArguments.get(RESOURCE);
                                } else {
                                    controller = namedArguments.get(SINGLE);
                                }
                                var controllerName = controller.toString();
                                mappingInfo.setController(controllerName);
                                parentResources.push(new ParentResource(controllerName, mappedURI, true));
                                try {
                                    invokeLastArgumentIfClosure(args);
                                } finally {
                                    parentResources.pop();
                                }
                                createSingleResourceRestfulMappings(controllerName, mappingInfo.getPlugin(), mappingInfo.getNamespace(), version, urlData, currentConstraints, calculateIncludes(namedArguments, DEFAULT_RESOURCE_INCLUDES));
                            } else if (namedArguments.containsKey(RESOURCES)) {
                                var controller = namedArguments.get(RESOURCES);
                                var controllerName = controller.toString();
                                mappingInfo.setController(controllerName);
                                parentResources.push(new ParentResource(controllerName, mappedURI, false));
                                try {
                                    urlDefiningMode = true;
                                    invokeLastArgumentIfClosure(args);
                                } finally {
                                    parentResources.pop();
                                    hasParent = !parentResources.isEmpty();
                                    if (!hasParent) {
                                        urlDefiningMode = false;
                                    }
                                }
                                createResourceRestfulMappings(controllerName, mappingInfo.getPlugin(), mappingInfo.getNamespace(), version, urlData, currentConstraints, calculateIncludes(namedArguments, DEFAULT_RESOURCES_INCLUDES));
                            }
                            else {
                                invokeLastArgumentIfClosure(args);
                                var urlMapping = getURLMappingForNamedArgs(namedArguments, urlData, mappedURI, isResponseCode, currentConstraints);
                                configureUrlMapping(urlMapping);
                                return urlMapping;
                            }
                        }
                        return null;
                    } finally {
                        if (binding != null && variables != null) {
                            variables.clear();
                        }
                        if (!hasParent) {
                            urlDefiningMode = true;
                        }
                    }
                } else if ((!urlDefiningMode || (!parentResources.isEmpty() && parentResources.peek().isGroup)) && CONSTRAINTS.equals(mappedURI)) {
                    if (args.length > 0 && (args[0] instanceof Closure<?>)) {
                        Closure<?> callable = (Closure<?>) args[0];
                        var builder = constraintsEvaluator.newConstrainedPropertyBuilder(UrlMapping.class);
                        for (var constrainedProperty : currentConstraints) {
                            builder.getConstrainedProperties().put(constrainedProperty.getPropertyName(), constrainedProperty);
                        }
                        callable.setResolveStrategy(Closure.DELEGATE_FIRST);
                        callable.setDelegate(builder);
                        callable.call();
                        return builder.getConstrainedProperties();
                    }
                    return Collections.emptyMap();
                } else {
                    log.error("Mapping: '{}' does not start with {} or is response code.", mappedURI, SLASH);
                    return super.invokeMethod(mappedURI, arg);
                }
            } finally {
                mappingInfoDeque.pop();
            }
        }