/*
* Weblounge: Web Content Management System
* Copyright (c) 2003 - 2011 The Weblounge Team
* http://entwinemedia.com/weblounge
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package ch.entwine.weblounge.common.impl.util;
import ch.entwine.weblounge.common.site.Site;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This is able to parse text content and replace any weblounge formatting
* codes by their xhtml equivalent.
*/
public final class Templates {
/** Pattern to match tag definitions */
static final Pattern tag = Pattern.compile(
"<\\s*webl:(\\w+)\\s*(\\w+\\s*=\\s*\".*?\"\\s*)*>(.*?)<\\s*/webl:(\\1)\\s*>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.UNICODE_CASE
);
/** Pattern to match encoded tag definitions */
static final Pattern tagEncoded = Pattern.compile(
"<\\s*webl:(\\w+)\\s*(\\w+\\s*=\\s*".*?"\\s*)*>(.*?)<\\s*/webl:(\\1)\\s*>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.UNICODE_CASE
);
/** Pattern to match attribute definitions */
static final Pattern attribute = Pattern.compile(
"(\\w+)\\s*=\\s*\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.UNICODE_CASE
);
/** Pattern to match encoded attribute definitions */
static final Pattern attributeEncoded = Pattern.compile(
"(\\w+)\\s*=\\s*"(.*?)"", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.UNICODE_CASE
);
/**
* This class is not intended to be instantiated.
*/
private Templates() {
// Nothing to be done here
}
/**
* Formats the given text by resolving any known codes like formatting,
* links etc.
*
* @param text the text to format
* @param encoded <code>true</code> if the text is html encoded
* @param site the site
*/
public static String format(String text, boolean encoded, Site site) {
StringBuffer result = new StringBuffer(text.length() + 1024);
Matcher m = (encoded) ? tagEncoded.matcher(text) : tag.matcher(text);
while (m.find()) {
m.appendReplacement(result, markup(m.group(1), getAttributes(m.group(2), encoded), format(m.group(3), encoded, site), encoded));
}
m.appendTail(result);
return result.toString();
}
/**
* Returns the body surrounded by the tag.
*
* @param tag the tag name
* @param attributes the attributes
* @param body the link body
* @param encoded <code>true</code> if the body is encoded
* @return the tag
*/
private static String markup(String tag, Map<String, String> attributes, String body, boolean encoded) {
if (tag == null)
return body;
StringBuffer b = new StringBuffer();
tag = tag.toLowerCase();
b.append("<");
b.append(tag);
for (Map.Entry<String, String> e : attributes.entrySet()) {
b.append(" ");
b.append(e.getKey());
b.append("=");
b.append("\"");
b.append(e.getValue());
b.append("\"");
}
b.append(">");
b.append(body);
b.append("</");
b.append(tag);
b.append(">");
return b.toString();
}
/**
* Extracts the attributes from the given string <code>s</code> and
* puts them into a map.
*
* @param text the string
* @param encoded <code>true</code> if the attributes are encoded
* @return the mapped attributes
*/
private static Map<String, String> getAttributes(String text, boolean encoded) {
Map<String, String> attributes = new HashMap<String, String>();
if (text != null) {
Matcher m = (encoded) ? attributeEncoded.matcher(text) : attribute.matcher(text);
while (m.find()) {
attributes.put(m.group(1), m.group(2));
}
}
return attributes;
}
}