package org.freeplane.features.export.mindmapmode;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.ui.ExampleFileFilter;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.util.LogUtils;
import org.freeplane.core.util.TextUtils;
class XsltExportEngineFactory {
final private static String EXPORT_FILTER_PATTERN = "^.*MINDMAPEXPORTFILTER\\s+(\\S+)\\s+(.*)(?:\\s+-->)?$";
/** A pattern which is "MINDMAPEXPORTFILTER ext1;ext2;... File format description" */
final private static String FILE_NAME_PATTERN = "mm2([\\w]+)\\.xsl";
final private static Pattern COMPILED_EXPORT_FILTER_PATTERN = Pattern.compile(EXPORT_FILTER_PATTERN);
final private static Pattern COMPILED_FILE_NAME_PATTERN = Pattern.compile(FILE_NAME_PATTERN);
/** Maximum number of lines we read in each XSLT files for performance reasons */
final private static int MAX_READ_LINES = 5;
private ExportController controller;
/** This method populates the {@link #filterMap} and the {@link #fileFilters} field. */
void gatherXsltScripts(ExportController controller) {
try{
this.controller = controller;
gatherXsltScripts(getXsltSysDirectory());
// overwrite with user settings
gatherXsltScripts(getXsltUserDirectory());
}
finally{
this.controller = null;
}
}
/**
* A simple help function to get the directory where to search for XSLT
* export files distributed with Freeplane.
* @return The system directory where XSLT export files are supposed to be.
*/
File getXsltSysDirectory() {
return new File(ResourceController.getResourceController().getResourceBaseDir(), "xslt");
}
/**
* A simple help function to get the directory where to search for XSLT
* export files written by the user.
* @return The user directory where XSLT export files are supposed to be.
*/
File getXsltUserDirectory() {
return new File(ResourceController.getResourceController().getFreeplaneUserDirectory(), "xslt");
}
/**
* This methods checks all readable files ending in '.xsl' from a given directory,
* and passes them to the method {@link #extractFilterFromFile}.
* @param xsltdir the directory where XSLT files are to be searched for
*/
private void gatherXsltScripts(final File xsltdir) {
if (!(xsltdir.isDirectory() && xsltdir.canRead())) {
return;
}
// we list the files using an anonymous filter class that accepts only files
// readable by the user and with name ending in .xsl
final File xsltFiles[] = xsltdir.listFiles(new java.io.FileFilter() {
public boolean accept(final File pathname) {
return (pathname.isFile() && pathname.canRead() && pathname.getPath().toLowerCase().endsWith(".xsl"));
}
});
// we compile the pattern for performance reasons.
// then for each found file, we check and extract a potentially present filter
for (int i = 0; i < xsltFiles.length; i++) {
extractFilterFromFile(xsltFiles[i]);
}
}
/**
* The function checks if the pattern matches with one of the lines in the file.
* @param xsltFile the file to open and search a line matching the pattern.
*/
private void extractFilterFromFile(final File xsltFile) {
BufferedReader xsl = null;
try {
xsl = new BufferedReader(new FileReader(xsltFile));
String line;
int l = 0;
boolean keyFound = false;
// ...we open it and check if it contains the right marker
while ((line = xsl.readLine()) != null && l < MAX_READ_LINES) {
final Matcher m = COMPILED_EXPORT_FILTER_PATTERN.matcher(line);
if (m.matches()) { // if it does
keyFound = true;
final String[] extensions = m.group(1).split("\\s*;\\s*");
String description = m.group(2).trim();
if(description.startsWith("%")){
description = TextUtils.getText(description.substring(1));
}
addXsltFile(extensions, description, xsltFile);
// we want to allow for more than one filter line per XSLT file
// so we don't exit once we've found one and even account for
// the fact that we might trespass the MAX_READ_LINES limit
l--;
}
l++;
}
if (keyFound) {
return;
}
final Matcher m = COMPILED_FILE_NAME_PATTERN.matcher(xsltFile.getName());
if (m.matches()) { // if it does
final String extension = m.group(1);
final String description = TextUtils.format("exported_file", extension);
addXsltFile(new String[] { extension }, description, xsltFile);
}
}
catch (final IOException e) {
LogUtils.warn(e);
UITools.errorMessage(TextUtils.getText("export_failed"));
}
finally {
if (xsl != null) {
try {
xsl.close();
}
catch (final IOException e) {
LogUtils.severe(e);
}
}
}
}
private void addXsltFile(final String[] extensions, String description, final File xsltFile) {
final ExampleFileFilter filter = new ExampleFileFilter(extensions, TextUtils.getOptionalTranslation(description));
final XsltExportEngine exporter = new XsltExportEngine(xsltFile);
controller.addExportEngine(filter, exporter);
}
}