package tk.eclipse.plugin.jspeditor.editors;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jp.aonir.fuzzyxml.FuzzyXMLAttribute;
import jp.aonir.fuzzyxml.FuzzyXMLDocument;
import jp.aonir.fuzzyxml.FuzzyXMLElement;
import jp.aonir.fuzzyxml.FuzzyXMLNode;
import jp.aonir.fuzzyxml.FuzzyXMLParser;
import jp.aonir.fuzzyxml.internal.RenderContext;
import org.eclipse.ui.IFileEditorInput;
import tk.eclipse.plugin.htmleditor.HTMLPlugin;
import tk.eclipse.plugin.htmleditor.HTMLUtil;
import tk.eclipse.plugin.htmleditor.ICustomTagConverter;
import tk.eclipse.plugin.htmleditor.ICustomTagConverterContributer;
/**
* This class provides some utility methods to convert JSP to HTML for preview.
*/
public class JSPPreviewConverter {
private static Pattern petternScript = Pattern.compile("<%(.*?)%>", Pattern.DOTALL);
private static Pattern petternTagBegin = Pattern.compile("<(|/)((\\w+?):(.*?))>");
/**
* Converts JSP to HTML for preview.
*
* @param jsp JSP
* @return converted HTML
*/
public static String convertJSP(IFileEditorInput input, String jsp) {
// get JSPInfo
JSPInfo info = JSPInfo.getJSPInfo(input.getFile(), jsp);
// remove JSP comments
//jsp = jsp.replaceAll("<%--(.|\n|\r)*?--%>","");
jsp = HTMLUtil.comment2space(jsp, false);
// split by <body>
String lower = jsp.toLowerCase();
int index = lower.indexOf("<body");
int end = lower.indexOf("</body>");
// if <body> doesn't exist, remove all
if (index == -1) {
jsp = petternScript.matcher(jsp).replaceAll("");
jsp = petternTagBegin.matcher(jsp).replaceAll("");
return jsp;
}
if (end == -1) {
end = jsp.length();
}
else {
end = end + 7;
}
String head = jsp.substring(0, index);
String body = jsp.substring(index, end);
// before <body>
head = petternScript.matcher(head).replaceAll("");
head = petternTagBegin.matcher(head).replaceAll("");
// after <body>
body = processScript(body);
body = processTag(body, info);
body = body.replaceAll("&nbsp;", " ");
body = body.replaceAll("'", "'");
return "<html>" + head + body + "</html>";
}
/**
* Process scriptlet.
*
* @param jsp JSP
* @return converted JSP
*/
private static String processScript(String jsp) {
StringBuffer sb = new StringBuffer();
Matcher matcher = petternScript.matcher(jsp);
int index = 0;
while (matcher.find()) {
sb.append(jsp.substring(index, matcher.start()));
sb.append(HTMLUtil.escapeHTML(matcher.group(0)));
index = matcher.end();
}
if (index < jsp.length() - 1) {
sb.append(jsp.substring(index));
}
return sb.toString();
}
/**
* This method should be private, but it's required to be public...
*
* @param element
* @param info
* @return
*/
public static String processElement(FuzzyXMLElement element, JSPInfo info) {
StringBuffer sb = new StringBuffer();
if (element.getName().indexOf(":") != -1) {
String tagName = element.getName();
String[] dim = tagName.split(":");
// get URI from prefix
String uri = info.getTaglibUri(dim[0]);
// get converter
ICustomTagConverter converter = null;
if (uri != null) {
ICustomTagConverterContributer contributer = HTMLPlugin.getDefault().getCustomTagContributer(uri);
if (contributer != null) {
converter = contributer.getConverter(dim[1]);
}
}
if (converter != null) {
HashMap<String, String> attrMap = new HashMap<String, String>();
FuzzyXMLAttribute[] attrs = element.getAttributes();
for (int i = 0; i < attrs.length; i++) {
attrMap.put(attrs[i].getName(), attrs[i].getValue());
}
sb.append(converter.process(attrMap, element.getChildren(), info));
return sb.toString();
}
}
if (element.getChildren().length == 0) {
sb.append(element.toXMLString(new RenderContext(true)));
}
else {
sb.append(element2startTag(element));
FuzzyXMLNode[] node = element.getChildren();
for (int i = 0; i < node.length; i++) {
if (node[i] instanceof FuzzyXMLElement) {
sb.append(processElement((FuzzyXMLElement) node[i], info));
}
else {
sb.append(node[i].toXMLString(new RenderContext(true)));
}
}
sb.append(element2closeTag(element));
}
return sb.toString();
}
private static String element2startTag(FuzzyXMLElement e) {
StringBuffer sb = new StringBuffer();
sb.append("<" + e.getName());
FuzzyXMLAttribute[] attr = e.getAttributes();
for (int i = 0; i < attr.length; i++) {
sb.append(" " + attr[i].getName() + "=\"" + attr[i].getValue() + "\"");
}
sb.append(">");
return sb.toString();
}
private static String element2closeTag(FuzzyXMLElement e) {
return "</" + e.getName() + ">";
}
/**
* Process taglibs.
*
* @param jsp JSP
* @param info JSPInfo
* @return processed JSP
*/
private static String processTag(String jsp, JSPInfo info) {
FuzzyXMLDocument doc = new FuzzyXMLParser(false).parse(jsp);
FuzzyXMLNode[] nodes = doc.getDocumentElement().getChildren();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < nodes.length; i++) {
if (nodes[i] instanceof FuzzyXMLElement) {
sb.append(processElement((FuzzyXMLElement) nodes[i], info));
}
}
return sb.toString();
}
}