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); } }