Convertir urls a enlaces Html en Java

Esta semana me he encontrado con un problema interesante en el trabajo: en una aplicación en desarrollo se usa un editor wysiwyg que no traduce de forma automática una url al código html necesario para que se convierta en un enlace. Y además tampoco se puede tocar el código javascript del editor, para no tener problemas con la licencia de uso y distribución.

Así que la única solución que quedaba era traducir esas urls a html en el servicio de negocio (Java), con la problemática de tener que detectarlas y además distinguir si esas urls ya formaban parte de un código html bien formado, o si estaban repetidas.

Es decir que si en el editor se escribe:

http://www.treelogic.com

La función nos devolvería el código html para que se represente como un enlace:

http://www.treelogic.com

En cambio, con el siguiente código, no debería alterar nada, pues las urls pertenecen a html bien formado:

http://www.google.es
logo google

Tras mucho buscar, y ver que todas las soluciones se referían sólo al problema de identificar una url en un string, encontré una gran ayuda en la documentación de la clase Pattern y en concreto el apartado de Special constructs (non-capturing), para poder ignorar las urls que ya forman parte de código html válido.

La función en cuestión:

	/**
	 * Finds all URLs in a given String and converts them to the html link code
	 * ignoring the urls used in existing html code.
	 *
	 * @param content
	 * @return content
	 * @author Alberto Calderón Queimadelos
	 */
	public String convertUrlsToLinks(String content) {
		Pattern URLPattern = Pattern.compile("(?<!=\")(https?|ftp|file)://[-a-" +
				"zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_| ](?=<)(?!</a>)");
		Matcher linkMatcher = URLPattern.matcher(content);
		String subString;
		while (linkMatcher.find()) {
			subString = content.substring(linkMatcher.start(),linkMatcher.end());
			content=linkMatcher.replaceFirst(" <a href=\"" + subString + "\" " +
				"target=\"_blank\">" + subString + "</a> ");
			linkMatcher = URLPattern.matcher(content);
		}
		return content;
	}

La expresión regular explicada:

  • (?<!=\”) Se ignoran todas las urls que comiencen con un =”, para evitar todas las que se usen en un src=”", href=”", img=”", value=”", data=”" ó codebase=”"
  • (https?|ftp|file) Las urls pueden comenzar por http, https, ftp o file.
  • ://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_| ] El patrón principal de la url.
  • (?=<) Si terminan en < no lo cogemos como parte de la url, pues podría ser un </p>, <br />, etc…
  • (?!</a>) Además ignora todas las que terminen en </a> para evitar las que formen parte de un enlace.

Comentar..