/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.cst.doc.functions.internal.content;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.velocity.VelocityContext;
import org.eclipse.help.IHelpContentProducer;
import org.w3c.dom.Element;
import com.google.common.io.Files;
import de.fhg.igd.slf4jplus.ALogger;
import de.fhg.igd.slf4jplus.ALoggerFactory;
import eu.esdihumboldt.cst.doc.functions.FunctionReferenceConstants;
import eu.esdihumboldt.hale.common.align.extension.category.Category;
import eu.esdihumboldt.hale.common.align.extension.category.CategoryExtension;
import eu.esdihumboldt.hale.common.align.extension.function.FunctionDefinition;
import eu.esdihumboldt.hale.common.align.extension.function.FunctionParameterDefinition;
import eu.esdihumboldt.hale.common.align.extension.function.FunctionUtil;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.doc.util.content.AbstractVelocityContent;
import eu.esdihumboldt.util.xml.XmlUtil;
/**
* Provides content for function documentation.
*
* @author Simon Templer
*/
public class FunctionReferenceContent extends AbstractVelocityContent
implements FunctionReferenceConstants {
private static final ALogger log = ALoggerFactory.getLogger(FunctionReferenceContent.class);
/**
* Directory for storing the generated images.
*/
private File tempDir;
private static final Method imageContentMethod = loadImageContentMethod();
private static Method loadImageContentMethod() {
try {
FunctionReferenceContent.class.getClassLoader()
.loadClass("eu.esdihumboldt.hale.ui.util.graph.OffscreenGraph");
Class<?> clazz = FunctionReferenceContent.class.getClassLoader().loadClass(
"eu.esdihumboldt.cst.doc.functions.internal.content.image.ImageContent");
return clazz.getMethod("getImageContent", String.class, File.class);
} catch (Throwable e) {
log.warn("Could not load image content method for function help", e);
return null;
}
}
/**
* @see IHelpContentProducer#getInputStream(String, String, Locale)
*/
@Override
public InputStream getInputStream(String pluginID, String href, Locale locale) {
if (href.startsWith(FUNCTION_TOPIC_PATH)) {
// it's a function
String func_id = href.substring(FUNCTION_TOPIC_PATH.length());
// strip everything after a ?
int ind = func_id.indexOf('?');
if (ind >= 0) {
func_id = func_id.substring(0, ind);
}
// strip the .*htm? ending
if (func_id.endsWith("html") || func_id.endsWith("htm")) {
func_id = func_id.substring(0, func_id.lastIndexOf('.'));
}
// .png ending
if (func_id.endsWith(".png")) {
func_id = func_id.substring(0, func_id.lastIndexOf('.'));
try {
return getImageContent(func_id);
} catch (Exception e) {
e.printStackTrace();
}
}
// /icon ending
if (func_id.endsWith("/icon")) {
func_id = func_id.substring(0, func_id.lastIndexOf('/'));
try {
return getIconContent(func_id);
} catch (Exception e) {
e.printStackTrace();
}
}
else {
try {
return getFunctionContent(func_id);
} catch (Exception e) {
log.error("Error creating help content", e);
}
}
}
return null;
}
private InputStream getImageContent(String func_id) {
if (imageContentMethod == null) {
return null;
}
if (tempDir == null) {
tempDir = Files.createTempDir();
tempDir.deleteOnExit();
}
try {
return (InputStream) imageContentMethod.invoke(null, func_id, tempDir);
} catch (Exception e) {
log.error("Error getting image content for function " + func_id);
}
return null;
}
/**
* @see AbstractVelocityContent#getTemplate(String)
*/
@Override
protected InputStream getTemplate(String templateId) throws Exception {
return FunctionReferenceContent.class.getResource("template.html").openStream();
}
private InputStream getFunctionContent(String func_id) throws Exception {
// maps "function" to the real function ID (used by the template)
final FunctionDefinition<?> function = FunctionUtil.getFunction(func_id, null);
if (function == null) {
log.warn("Unknown function " + func_id);
return null;
}
Callable<VelocityContext> contextFactory = new Callable<VelocityContext>() {
@Override
public VelocityContext call() throws Exception {
VelocityContext context = new VelocityContext();
context.put("showImage", imageContentMethod != null);
context.put("function", function);
// Map<paramDisplayName, sampleDataStringRepresentation>
Map<String, String> parameterDocu = new HashMap<String, String>();
for (FunctionParameterDefinition param : function.getDefinedParameters()) {
if (param.getValueDescriptor() != null
&& param.getValueDescriptor().getSampleData() != null) {
Value sample = param.getValueDescriptor().getSampleData();
if (sample.isRepresentedAsDOM()) {
// get DOM Element as String
Element ele = sample.getDOMRepresentation();
StringWriter writer = new StringWriter();
StreamResult formattedXmlString = new StreamResult(writer);
XmlUtil.prettyPrint(new DOMSource(ele), formattedXmlString);
// escape special chars to display xml code on html
String xmlString = formattedXmlString.getWriter().toString();
xmlString = StringEscapeUtils.escapeXml(xmlString);
parameterDocu.put(param.getDisplayName(), xmlString);
}
else {
parameterDocu.put(param.getDisplayName(),
sample.getStringRepresentation());
}
}
}
context.put("parameterDocu", parameterDocu);
if (function.getCategoryId() != null) {
String categoryId = function.getCategoryId();
Category category = (CategoryExtension.getInstance().get(categoryId));
// String category = categoryId.substring(categoryId
// .lastIndexOf(".") + 1);
//
// category = capitalize(category);
context.put("category", category);
}
// creating path for the file to be included
URL help_url = function.getHelpURL();
if (help_url != null) {
String help_path = help_url.getPath();
String bundle = function.getDefiningBundle();
StringBuffer sb_include = new StringBuffer();
sb_include.append(bundle);
sb_include.append(help_path);
sb_include.append("/help");
String final_help_url = sb_include.toString();
context.put("include", final_help_url);
}
return context;
}
};
return getContentFromTemplate(func_id, "function", contextFactory);
}
private InputStream getIconContent(String func_id) {
FunctionDefinition<?> function = FunctionUtil.getFunction(func_id, null);
URL url = function.getIconURL();
try {
return url.openStream();
} catch (IOException e) {
log.warn("Icon loading failed.");
e.printStackTrace();
}
return null;
}
}