/*
* Freeplane - mind map editor
* Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.freeplane.features.export.mindmapmode;
import java.awt.image.RenderedImage;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URL;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import javax.swing.ListModel;
import javax.swing.filechooser.FileFilter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.lang.StringUtils;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.ui.ExampleFileFilter;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.util.Compat;
import org.freeplane.core.util.FileUtils;
import org.freeplane.core.util.LogUtils;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.icon.UIIcon;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.map.MapWriter.Mode;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.mode.ModeController;
import org.freeplane.features.url.UrlManager;
/**
* @author foltin To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class ExportWithXSLT extends AExportEngine {
/**
* @param map
*/
static void copyIconsToDirectory(final MapModel map, final String directoryName) {
final ListModel icons = map.getIconRegistry().getIconsAsListModel();
for (int i = 0; i < icons.getSize(); i++) {
final UIIcon icon = (UIIcon) icons.getElementAt(i);
final String iconName = icon.getName();
final StringBuilder sb = new StringBuilder(directoryName);
final int lastIndexOfSeparator = iconName.lastIndexOf('/');
if (lastIndexOfSeparator != -1) {
sb.append(File.separatorChar);
sb.append(iconName.substring(0, lastIndexOfSeparator));
}
final File destinationDirectory = new File(sb.toString());
destinationDirectory.mkdirs();
FileUtils.copyFromURL(icon.getUrl(), destinationDirectory);
}
}
/**
* For test purposes. True=no error
*/
private boolean mTransformResultWithoutError = false;
final private Properties properties;
private String name;
public ExportWithXSLT(final String name, final Properties properties) {
this.name = name;
this.properties = properties;
}
/**
*/
private void copyFilesFromResourcesToDirectory(final String directoryName, final String files,
final String filePrefix) {
final StringTokenizer tokenizer = new StringTokenizer(files, ",");
final File destinationDirectory = new File(directoryName);
while (tokenizer.hasMoreTokens()) {
final String next = tokenizer.nextToken();
FileUtils.copyFromResource(filePrefix, next, destinationDirectory);
}
}
/**
* @param map
*/
private boolean copyIcons(final MapModel map, final String directoryName) {
boolean success;
final String iconDirectoryName = directoryName + File.separatorChar + "icons";
success = FileUtils.createDirectory(iconDirectoryName);
if (success) {
ExportWithXSLT.copyIconsToDirectory(map, iconDirectoryName);
}
return success;
}
private boolean copyMap(final MapModel map, final String pDirectoryName) {
boolean success = true;
try {
final BufferedWriter fileout = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
pDirectoryName + File.separator + "map" + UrlManager.FREEPLANE_FILE_EXTENSION)));
final Mode mode = Mode.valueOf(getProperty("copymode", Mode.EXPORT.name()));
Controller.getCurrentModeController().getMapController().getFilteredXml(map, fileout, mode, Mode.EXPORT.equals(mode));
}
catch (final IOException e) {
success = false;
}
return success;
}
/**
* @param map
*/
private boolean createImageFromMap(MapModel map, final String directoryName) {
if (Controller.getCurrentController().getMapViewManager().getMapViewComponent() == null) {
return false;
}
final RenderedImage image = createBufferedImage(map);
if(image == null){
return false;
}
try {
final FileOutputStream out = new FileOutputStream(directoryName + File.separator + "image.png");
ImageIO.write(image, "png", out);
out.close();
return true;
}
catch (final IOException e1) {
LogUtils.severe(e1);
return false;
}
}
/**
* @param create_image
*/
private String getAreaCode(final boolean create_image) {
String areaCode = "";
if (create_image) {
areaCode = Controller.getCurrentController().getMapViewManager().createHtmlMap();
}
return areaCode;
}
/**
* @param mode
* @throws IOException
*/
private String getMapXml(final Mode mode) throws IOException {
final StringWriter writer = new StringWriter();
final ModeController modeController = Controller.getCurrentModeController();
final Controller controller = modeController.getController();
final MapModel map = controller.getMap();
modeController.getMapController().getFilteredXml(map, writer, mode, Mode.EXPORT.equals(mode));
return writer.getBuffer().toString();
}
String getProperty(final String key) {
final String property = getProperty(key, null);
if (property == null || !property.startsWith("$")) {
return property;
}
return System.getProperty(property.substring(1), null);
}
String getProperty(final String key, final String value) {
return properties.getProperty(key, value);
}
public boolean isTransformResultWithoutError() {
return mTransformResultWithoutError;
}
/**
* @param saveFile
*/
public void export(final MapModel map, final File saveFile) {
try {
mTransformResultWithoutError = true;
final boolean create_image = StringUtils.equals(getProperty("create_html_linked_image"), "true");
final String areaCode = getAreaCode(create_image);
final String xsltFileName = getProperty("xslt_file");
boolean success = transformMapWithXslt(xsltFileName, saveFile, areaCode);
if (!success) {
JOptionPane.showMessageDialog(UITools.getFrame(), getProperty("error_applying_template"), "Freeplane",
JOptionPane.ERROR_MESSAGE);
return;
}
if (success && StringUtils.equals(getProperty("create_dir"), "true")) {
final String directoryName = saveFile.getAbsolutePath() + "_files";
success = FileUtils.createDirectory(directoryName);
if (success) {
final String files = getProperty("files_to_copy");
final String filePrefix = getProperty("file_prefix");
copyFilesFromResourcesToDirectory(directoryName, files, filePrefix);
}
if (success && StringUtils.equals(getProperty("copy_icons"), "true")) {
success = copyIcons(map, directoryName);
}
if (success && StringUtils.equals(getProperty("copy_map"), "true")) {
success = copyMap(map, directoryName);
}
if (success && create_image) {
success = createImageFromMap(map, directoryName);
}
}
if (!success) {
JOptionPane.showMessageDialog(UITools.getFrame(), getProperty("error_creating_directory"), "Freeplane",
JOptionPane.ERROR_MESSAGE);
return;
}
if (StringUtils.equals(getProperty("load_file"), "true")) {
Controller.getCurrentController().getViewController().openDocument(Compat.fileToUrl(saveFile));
}
}
catch (final Exception e) {
LogUtils.severe(e);
mTransformResultWithoutError = false;
}
}
/**
* @throws IOException
*/
private boolean transformMapWithXslt(final String xsltFileName, final File saveFile, final String areaCode)
throws IOException {
final Mode mode = Mode.valueOf(getProperty("mode", Mode.EXPORT.name()));
final String map = getMapXml(mode);
final StringReader reader = new StringReader(map);
ResourceController resourceController = ResourceController.getResourceController();
final URL xsltUrl = resourceController.getResource(xsltFileName);
if (xsltUrl == null) {
LogUtils.severe("Can't find " + xsltFileName + " as resource.");
throw new IllegalArgumentException("Can't find " + xsltFileName + " as resource.");
}
final InputStream xsltFile = new BufferedInputStream(xsltUrl.openStream());
final Source xsltSource = new StreamSource(xsltFile);
final Result result = new StreamResult(saveFile);
try {
final TransformerFactory transFact = TransformerFactory.newInstance();
final Transformer trans = transFact.newTransformer(xsltSource);
trans.setParameter("destination_dir", saveFile.getName() + "_files/");
trans.setParameter("area_code", areaCode);
trans.setParameter("folding_type", resourceController.getProperty(
"html_export_folding"));
String[] parameters = getProperty("set_properties", "").split(",\\s*");
StringBuilder sb = new StringBuilder();
for(String p : parameters){
String value = resourceController.getProperty(p, null);
if(value != null && ! value.equals(resourceController.getDefaultProperty(p))){
sb.append(p);
sb.append('=');
sb.append(value);
sb.append("$$$");
}
}
trans.setParameter("propertyList", sb.toString());
trans.transform(new StreamSource(reader), result);
}
catch (final Exception e) {
LogUtils.warn(e);
return false;
}
finally {
FileUtils.silentlyClose(xsltFile);
}
return true;
}
public FileFilter getFileFilter() {
return new ExampleFileFilter(getProperty("file_type"), TextUtils.getText(name + ".text"));
}
}