in grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/DefaultLinkGenerator.groovy [108:291]
String link(Map attrs, String encoding = 'UTF-8') {
def writer = new StringBuilder()
// prefer URI attribute
boolean includeContext = GrailsClassUtils.getBooleanFromMap(ATTRIBUTE_INCLUDE_CONTEXT, attrs, true)
if (attrs.get(ATTRIBUTE_URI) != null) {
def uri = attrs.get(ATTRIBUTE_URI).toString()
if(!isUriAbsolute(uri)){
final base = handleAbsolute(attrs)
if (base != null) {
writer.append base
}
else if(includeContext) {
def cp = attrs.get(ATTRIBUTE_CONTEXT_PATH)
if (cp == null) cp = getContextPath()
if (cp != null)
writer.append cp
}
}
writer.append uri
def params = attrs.get(ATTRIBUTE_PARAMS)
if(params instanceof Map) {
def charset = GrailsWebUtil.DEFAULT_ENCODING
def paramString = params.collect { Map.Entry entry ->
def encodedKey = URLEncoder.encode(entry.key as String, charset)
def encodedValue = URLEncoder.encode(entry.value as String, charset)
"$encodedKey=$encodedValue"
}.join('&')
writer.append(uri.indexOf('?') >= 0 ? '&' : '?')
.append paramString
}
}
else if (attrs.get(ATTRIBUTE_RELATIVE_URI) != null) {
String relativeUri = attrs.get(ATTRIBUTE_RELATIVE_URI)
String forwardUri = WebUtils.getForwardURI(requestStateLookupStrategy.webRequest.request)
int index = forwardUri.lastIndexOf('/')
if (index != -1) {
writer.append forwardUri.substring(0, index + 1)
}
writer.append relativeUri
}
else {
// prefer a URL attribute
Map urlAttrs = attrs
final urlAttribute = attrs.get(ATTRIBUTE_URL)
if (urlAttribute instanceof Map) {
urlAttrs = (Map)urlAttribute
}
if (!urlAttribute || urlAttribute instanceof Map) {
final controllerAttribute = urlAttrs.get(ATTRIBUTE_CONTROLLER)
final resourceAttribute = urlAttrs.get(ATTRIBUTE_RESOURCE)
String controller
String action = urlAttrs.get(ATTRIBUTE_ACTION)?.toString()
def id = urlAttrs.get(ATTRIBUTE_ID)
String httpMethod;
final methodAttribute = urlAttrs.get(ATTRIBUTE_METHOD)
final paramsAttribute = urlAttrs.get(ATTRIBUTE_PARAMS)
Map params = paramsAttribute instanceof Map ? (Map) paramsAttribute : [:]
if (resourceAttribute) {
String resource
if (resourceAttribute instanceof CharSequence)
resource = resourceAttribute.toString()
else {
PersistentEntity persistentEntity = (mappingContext != null) ? mappingContext.getPersistentEntity(resourceAttribute.getClass().getName()) : null
boolean hasId = false
if(persistentEntity != null) {
resource = persistentEntity.getDecapitalizedName()
hasId = true
} else if (DomainClassArtefactHandler.isDomainClass(resourceAttribute.getClass(), true)) {
resource = GrailsNameUtils.getPropertyName(resourceAttribute.getClass())
hasId = true
} else if (resourceAttribute instanceof Class) {
resource = GrailsNameUtils.getPropertyName(resourceAttribute)
} else {
resource = resourceAttribute.toString()
}
if(!id && hasId) {
id = getResourceId(resourceAttribute)
}
}
List tokens = resource.contains('/') ? resource.tokenize('/') :[resource]
controller = controllerAttribute?:tokens[-1]
if (tokens.size()>1) {
for(t in tokens[0..-2]) {
final key = "${t}Id".toString()
final attr = urlAttrs.remove(key)
// the params value might not be null
// only overwrite if urlAttrs actually had the key
if (attr) {
params[key] = attr
}
}
}
if (!methodAttribute && action) {
httpMethod = REST_RESOURCE_ACTION_TO_HTTP_METHOD_MAP.get(action.toString())
if (!httpMethod) {
httpMethod = HttpMethod.GET.toString()
}
}
else if (methodAttribute && !action) {
def method = methodAttribute.toString().toUpperCase()
httpMethod = method
if (method == 'GET' && id) method = "${method}_ID".toString()
action = REST_RESOURCE_HTTP_METHOD_TO_ACTION_MAP[method]
}
else {
httpMethod = methodAttribute == null ? requestStateLookupStrategy.getHttpMethod() ?: UrlMapping.ANY_HTTP_METHOD : methodAttribute.toString()
}
}
else {
controller = controllerAttribute == null ? requestStateLookupStrategy.getControllerName() : controllerAttribute.toString()
httpMethod = methodAttribute == null ? requestStateLookupStrategy.getHttpMethod() ?: UrlMapping.ANY_HTTP_METHOD : methodAttribute.toString()
}
String convertedControllerName = grailsUrlConverter.toUrlElement(controller)
boolean isDefaultAction = false
if (controller && !action) {
action = requestStateLookupStrategy.getActionName(convertedControllerName)
isDefaultAction = true
}
String convertedActionName = action
if (action) {
convertedActionName = grailsUrlConverter.toUrlElement(action)
}
String frag = urlAttrs.get(ATTRIBUTE_FRAGMENT)?.toString()
def mappingName = urlAttrs.get(ATTRIBUTE_MAPPING)
if (mappingName != null) {
params.mappingName = mappingName
}
def url
if (id != null) {
params.put(ATTRIBUTE_ID, id)
}
def pluginName = attrs.get(UrlMapping.PLUGIN)?.toString()
def namespace = attrs.get(UrlMapping.NAMESPACE)?.toString()
if (namespace == null) {
if (controller == requestStateLookupStrategy.controllerName) {
namespace = requestStateLookupStrategy.controllerNamespace
}
}
UrlCreator mapping = urlMappingsHolder.getReverseMappingNoDefault(controller,action,namespace,pluginName,httpMethod,params)
if (mapping == null && isDefaultAction) {
mapping = urlMappingsHolder.getReverseMappingNoDefault(controller,null,namespace,pluginName,httpMethod,params)
}
if (mapping == null) {
mapping = urlMappingsHolder.getReverseMapping(controller,action,namespace,pluginName,httpMethod,params)
}
boolean absolute = isAbsolute(attrs)
if (!absolute) {
url = mapping.createRelativeURL(convertedControllerName, convertedActionName, namespace, pluginName, params, encoding, frag)
final contextPathAttribute = attrs.get(ATTRIBUTE_CONTEXT_PATH)
final cp = contextPathAttribute == null ? getContextPath() : contextPathAttribute
if (attrs.get(ATTRIBUTE_BASE) || cp == null) {
attrs.put(ATTRIBUTE_ABSOLUTE, true)
writer.append handleAbsolute(attrs)
}
else if(includeContext) {
writer.append cp
}
writer.append url
}
else {
url = mapping.createRelativeURL(convertedControllerName, convertedActionName, namespace, pluginName, params, encoding, frag)
writer.append handleAbsolute(attrs)
writer.append url
}
} else {
writer.append urlAttribute
}
}
return writer.toString()
}