package org.freeplane.plugin.script.filter; import groovy.lang.Script; import java.awt.Dimension; import java.awt.KeyboardFocusManager; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import javax.swing.JComponent; import javax.swing.JOptionPane; import org.freeplane.core.util.HtmlUtils; import org.freeplane.core.util.LogUtils; import org.freeplane.core.util.TextUtils; import org.freeplane.features.filter.condition.ASelectableCondition; import org.freeplane.features.map.NodeModel; import org.freeplane.features.mode.Controller; import org.freeplane.n3.nanoxml.XMLElement; import org.freeplane.plugin.script.ExecuteScriptException; import org.freeplane.plugin.script.ScriptingEngine; import org.freeplane.plugin.script.ScriptingPermissions; public class ScriptCondition extends ASelectableCondition { private static final String SCRIPT_FILTER_DESCRIPTION_RESOURCE = "plugins/script_filter"; private static final String SCRIPT_FILTER_ERROR_RESOURCE = "plugins/script_filter_error"; static final String NAME = "script_condition"; static final String SCRIPT = "SCRIPT"; final private String script; private Script compiledScript = null; private boolean canNotCompileScript = false; private boolean errorReported = false; static ASelectableCondition load(final XMLElement element) { return new ScriptCondition(element.getAttribute(SCRIPT, null)); } public ScriptCondition(final String script) { super(); this.script = script; } public boolean checkNode(final NodeModel node) { if(canNotCompileScript) return false; final ByteArrayOutputStream out = new ByteArrayOutputStream(); final PrintStream printStream = new PrintStream(out); final ScriptingPermissions formulaPermissions = ScriptingPermissions.getFormulaPermissions(); if(compiledScript == null) { try { compiledScript = ScriptingEngine.compileScriptCheckExceptions(script, ScriptingEngine.IGNORING_SCRIPT_ERROR_HANDLER, printStream, formulaPermissions); } catch (Exception e) { canNotCompileScript = true; return false; } } final Object result; try { result = ScriptingEngine.executeScript(node, script, compiledScript, printStream, formulaPermissions); if(result instanceof Boolean) return (Boolean) result; if(result instanceof Number) return ((Number) result).doubleValue() != 0; printStream.println(this + ": got '" + result + "' for " + node); printStream.close(); final String info = TextUtils.format(SCRIPT_FILTER_ERROR_RESOURCE, createDescription(), node.toString(), String.valueOf(result)); setErrorStatus(info); } catch (ExecuteScriptException e) { printStream.close(); final String info = TextUtils.format(SCRIPT_FILTER_ERROR_RESOURCE, createDescription(), node.toString(), out.toString()); setErrorStatus(info); } return false; } private void setErrorStatus(final String info) { if(! errorReported){ errorReported = true; JOptionPane.showMessageDialog(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(), info, TextUtils.getText("error"), JOptionPane.ERROR_MESSAGE); } LogUtils.warn(info); Controller.getCurrentController().getViewController().out(info.trim().replaceAll("\\s", " ").substring(0, 80)); } @Override protected String createDescription() { return TextUtils.format(SCRIPT_FILTER_DESCRIPTION_RESOURCE, script); } @Override protected JComponent createRendererComponent() { final JComponent renderer = super.createRendererComponent(); final Dimension preferredSize = renderer.getPreferredSize(); if(preferredSize.width > 200) { renderer.setPreferredSize(new Dimension(200, preferredSize.height)); } if(preferredSize.width > 200 || script.contains("\n")) { renderer.setToolTipText(HtmlUtils.plainToHTML(script)); } return renderer; } public void fillXML(final XMLElement child) { super.fillXML(child); child.setAttribute(SCRIPT, script); } @Override protected String getName() { return NAME; } }