/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.jsf.vpe.richfaces.template;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringBufferInputStream;
import java.util.HashMap;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.resources.IFile;
import org.jboss.tools.jsf.vpe.richfaces.HtmlComponentUtil;
import org.jboss.tools.jsf.vpe.richfaces.RichFacesTemplatesActivator;
import org.jboss.tools.vpe.editor.VpeSourceDomBuilder;
import org.jboss.tools.vpe.editor.context.VpePageContext;
import org.jboss.tools.vpe.editor.template.VpeAbstractTemplate;
import org.jboss.tools.vpe.editor.template.VpeCreationData;
import org.jboss.tools.vpe.editor.template.VpeCreatorUtil;
import org.mozilla.interfaces.nsIDOMDocument;
import org.mozilla.interfaces.nsIDOMElement;
import org.mozilla.interfaces.nsIDOMText;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import com.uwyn.jhighlight.renderer.Renderer;
import com.uwyn.jhighlight.renderer.XhtmlRendererFactory;
/**
*
* @author ezheleznyakov@exadel.com
*
*/
public class RichFacesInsertTemplate extends VpeAbstractTemplate {
private static String RESOURCE_NOT_FOUND_MESSAGE = "Resource was not found."; //$NON-NLS-1$
private static String RESOURCE_READING_ERROR_MESSAGE = "Resource reading error."; //$NON-NLS-1$
private static String HIGHLIGHT_ERROR_MESSAGE = "Error occured during highlight."; //$NON-NLS-1$
private static String ERROR_MESSAGE_STYLE = "color: red; font-weight: bold;"; //$NON-NLS-1$
private static String SRC_ATTR_NAME = "src"; //$NON-NLS-1$
private static String HIGHTLIGHT_ATTR_NAME = "highlight"; //$NON-NLS-1$
private static String CODE_TAG = "code>"; //$NON-NLS-1$
private static String CLASS = "class="; //$NON-NLS-1$
private static String STYLE = "style="; //$NON-NLS-1$
private static String OPEN_BRACKET = "{"; //$NON-NLS-1$
private static String CLOSE_BRACKET = "}"; //$NON-NLS-1$
private static String SPACE = " "; //$NON-NLS-1$
private static String SPAN_TAG = "<span style=\"color: rgb(255,255,255)\">_</span>"; //$NON-NLS-1$
private static String EMPTY_STRING = ""; //$NON-NLS-1$
private static String UTF8 = "utf-8"; //$NON-NLS-1$
private static String HTML = "html"; //$NON-NLS-1$
private static String XHTML = "xhtml"; //$NON-NLS-1$
private static String XML = "xml"; //$NON-NLS-1$
private static String JAVA = "java"; //$NON-NLS-1$
private static String CPP = "cpp"; //$NON-NLS-1$
private static String CPLUSPLUS = "c++"; //$NON-NLS-1$
private static String GROOVY = "groovy"; //$NON-NLS-1$
private static String LZX = "lzx"; //$NON-NLS-1$
private nsIDOMDocument visualDocument;
public VpeCreationData create(VpePageContext pageContext, Node sourceNode,
nsIDOMDocument visualDocument) {
this.visualDocument = visualDocument;
nsIDOMElement div = visualDocument
.createElement(HtmlComponentUtil.HTML_TAG_DIV);
VpeCreationData vpeCreationData = new VpeCreationData(div);
Element sourceElement = (Element)sourceNode;
String srcValue = sourceElement.getAttribute(SRC_ATTR_NAME);
String finalStr = ""; //$NON-NLS-1$
String buf = ""; //$NON-NLS-1$
// if there is no source show error message
if (!sourceElement.hasAttribute(SRC_ATTR_NAME) || "".equalsIgnoreCase(srcValue)) { //$NON-NLS-1$
div.setAttribute(HtmlComponentUtil.HTML_STYLE_ATTR, ERROR_MESSAGE_STYLE);
nsIDOMText text = visualDocument.createTextNode(RESOURCE_NOT_FOUND_MESSAGE);
div.appendChild(text);
return vpeCreationData;
}
BufferedReader br = null;
try {
IFile iFile = VpeCreatorUtil.getFile(srcValue, pageContext);
if (iFile==null || !iFile.isAccessible()) {
div.setAttribute(HtmlComponentUtil.HTML_STYLE_ATTR,
ERROR_MESSAGE_STYLE);
nsIDOMText text = visualDocument
.createTextNode(RESOURCE_READING_ERROR_MESSAGE);
div.appendChild(text);
return vpeCreationData;
}
File file = new File(iFile.getLocation().toOSString());
br = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
while ((buf = br.readLine()) != null)
finalStr += buf + "\n"; //$NON-NLS-1$
} catch (IOException e) {
div.setAttribute(HtmlComponentUtil.HTML_STYLE_ATTR,
ERROR_MESSAGE_STYLE);
nsIDOMText text = visualDocument
.createTextNode(RESOURCE_READING_ERROR_MESSAGE);
div.appendChild(text);
return vpeCreationData;
} finally {
try {
if(br!=null) {
br.close();
}
} catch (IOException e) {
RichFacesTemplatesActivator.getPluginLog().logError(e);
}
}
String highlightValue = sourceElement.getAttribute(HIGHTLIGHT_ATTR_NAME);
if (!sourceElement.hasAttribute(HIGHTLIGHT_ATTR_NAME) || !searchInSupportedTypes(highlightValue)) {
// finalStr = finalStr.replace('\n', ' ');
nsIDOMText text = visualDocument.createTextNode(finalStr);
div.appendChild(text);
return vpeCreationData;
}
Renderer renderer = XhtmlRendererFactory.getRenderer(highlightValue);
String transformStr = null;
try {
transformStr = renderer.highlight("", finalStr, UTF8, false); //$NON-NLS-1$
transformStr = convertString(transformStr, highlightValue);
Node node = parseTransformString(transformStr);
buildVisualNode(node, div);
} catch (IOException e1) {
div.setAttribute(HtmlComponentUtil.HTML_STYLE_ATTR, ERROR_MESSAGE_STYLE);
nsIDOMText text = visualDocument.createTextNode(HIGHLIGHT_ERROR_MESSAGE);
div.appendChild(text);
return vpeCreationData;
}
return vpeCreationData;
}
/**
*
* @param str
* @param highlightValue
* highlight attribute value
*/
private String convertString(String str, String highlightValue) {
HashMap<String, String> map = new HashMap<String, String>();
if (highlightValue.equalsIgnoreCase(HTML)
|| highlightValue.equalsIgnoreCase(XHTML)
|| highlightValue.equalsIgnoreCase(LZX))
highlightValue = XML;
if (highlightValue.equalsIgnoreCase(GROOVY))
highlightValue = JAVA;
if (highlightValue.equalsIgnoreCase(CPLUSPLUS))
highlightValue = CPP;
String sym = "." + highlightValue + "_"; //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i < str.length();) {
int start = str.indexOf(sym, i);
if (start == -1)
break;
int startBracket = str.indexOf(OPEN_BRACKET, start);
String key = str.substring(start + 1, startBracket - 1);
int endBracket = str.indexOf(CLOSE_BRACKET, startBracket);
String value = str.substring(startBracket + 2, endBracket - 2);
i = endBracket;
map.put(key, value);
}
int start = str.indexOf(CODE_TAG);
int end = str.indexOf(CODE_TAG, start + 1);
str = str.substring(start - 1, end + 5);
str = str.replaceAll(CLASS, STYLE);
Set<String> set = map.keySet();
for (String key : set) {
String value = map.get(key);
str = str.replaceAll(key, value);
}
str = str.replace(SPACE, SPAN_TAG);
return str;
}
/**
*
* @param fileTransform
*/
@SuppressWarnings("deprecation")
public Node parseTransformString(String transformString) {
DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
Document doc = null;
Node node = null;
try {
builder = fact.newDocumentBuilder();
doc = builder.parse(new StringBufferInputStream(transformString));
node = doc.getElementsByTagName("code").item(0); //$NON-NLS-1$
} catch (IOException e) {
return node;
} catch (SAXException e) {
return node;
} catch (ParserConfigurationException e) {
return node;
}
return node;
}
/**
*
* @param highlightValue
* value of highlight attribute
* @return true of highlight value correct
*/
private boolean searchInSupportedTypes(String highlightValue) {
if (highlightValue == null)
return true;
if (highlightValue.trim().equals(EMPTY_STRING))
return false;
Set<?> set = XhtmlRendererFactory.getSupportedTypes();
for (Object object : set)
if (highlightValue.equalsIgnoreCase((String) object))
return true;
return false;
}
/**
*
* @param node
* @param el
* @return
*/
private void buildVisualNode(Node node, nsIDOMElement el) {
if (node instanceof Text) {
nsIDOMText text = visualDocument.createTextNode(node
.getTextContent());
el.appendChild(text);
} else {
nsIDOMElement elem = visualDocument.createElement(node
.getNodeName());
el.appendChild(elem);
for (int i = 0; i < node.getAttributes().getLength(); i++)
elem.setAttribute(node.getAttributes().item(i).getNodeName(),
node.getAttributes().item(i).getNodeValue());
for (int i = 0; i < node.getChildNodes().getLength(); i++)
buildVisualNode(node.getChildNodes().item(i), elem);
}
}
/**
* Checks, whether it is necessary to re-create an element at change of
* attribute
*
* @param pageContext
* Contains the information on edited page.
* @param sourceElement
* The current element of the source tree.
* @param visualDocument
* The document of the visual tree.
* @param visualNode
* The current node of the visual tree.
* @param data
* The arbitrary data, built by a method <code>create</code>
* @param name
* Attribute name
* @param value
* Attribute value
* @return <code>true</code> if it is required to re-create an element at
* a modification of attribute, <code>false</code> otherwise.
*/
public boolean recreateAtAttrChange(VpePageContext pageContext,
Element sourceElement, nsIDOMDocument visualDocument,
nsIDOMElement visualNode, Object data, String name, String value) {
return true;
}
@Override
public void setSourceAttributeSelection(VpePageContext pageContext,
Element sourceElement, int offset, int length, Object data) {
VpeSourceDomBuilder sourceBuilder = pageContext.getSourceBuilder();
sourceBuilder.setSelection(sourceElement, 0, 0);
}
}