package org.freeplane.plugin.script.addons;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Vector;
import org.freeplane.main.addons.AddOnProperties;
import org.freeplane.n3.nanoxml.XMLElement;
import org.freeplane.plugin.script.ExecuteScriptAction.ExecutionMode;
import org.freeplane.plugin.script.ScriptingEngine;
import org.freeplane.plugin.script.ScriptingPermissions;
/** For all add-ons that are installed via installScriptAddon.groovy - themes and script collections. */
public class ScriptAddOnProperties extends AddOnProperties {
public static class Script {
public String name;
public File file;
public ExecutionMode executionMode;
public String menuTitleKey;
public String menuLocation;
public ScriptingPermissions permissions;
public String keyboardShortcut;
public String scriptBody;
// transient - copy of AddOnProperties.active
public boolean active = true;
public String toString() {
return name + "(" + executionMode + "/" + menuTitleKey + "/" + menuLocation + "" + ")";
}
}
private List<Script> scripts;
public ScriptAddOnProperties(String name) {
super(AddOnType.SCRIPT);
setName(name);
}
public ScriptAddOnProperties(final XMLElement addOnelement) {
super(AddOnType.SCRIPT, addOnelement);
this.scripts = parseScripts(addOnelement.getChildrenNamed("scripts"));
validate();
}
private void validate() {
if (scripts == null)
throw new RuntimeException(this + ": on parsing add-on XML file: scripts may not be null");
for (Script script : scripts) {
if (script.name == null)
throw new RuntimeException(this + ": on parsing add-on XML file: no name");
if (script.file == null)
throw new RuntimeException(this + ": on parsing add-on XML file: Script file " + script + "not defined");
if (!script.file.exists())
throw new RuntimeException(this + ": on parsing add-on XML file: Script " + script + " does not exist");
if (script.executionMode == null)
throw new RuntimeException(this + ": on parsing add-on XML file: no execution_mode");
if (script.menuTitleKey == null)
throw new RuntimeException(this + ": on parsing add-on XML file: no menu title key");
if (script.menuLocation == null)
throw new RuntimeException(this + ": on parsing add-on XML file: no menu location");
if (script.permissions == null)
throw new RuntimeException(this + ": on parsing add-on XML file: no permissions");
}
}
private List<Script> parseScripts(Vector<XMLElement> xmlElements) {
final ArrayList<Script> scripts = new ArrayList<Script>();
if (xmlElements == null || xmlElements.isEmpty())
return scripts;
for (XMLElement scriptXmlNode : xmlElements.get(0).getChildren()) {
final Script script = new Script();
for (Entry<Object, Object> entry : scriptXmlNode.getAttributes().entrySet()) {
if (entry.getKey().equals("name")) {
script.name = (String) entry.getValue();
}
else if (entry.getKey().equals("file")) {
script.file = new File(entry.getValue().toString());
}
else if (entry.getKey().equals("executionMode")) {
script.executionMode = parseExecutionMode(entry.getValue().toString());
}
else if (entry.getKey().equals("menuTitleKey")) {
script.menuTitleKey = entry.getValue().toString();
}
else if (entry.getKey().equals("menuLocation")) {
script.menuLocation = entry.getValue().toString();
}
}
script.permissions = new ScriptingPermissions(scriptXmlNode.getAttributes());
fixUnsetFile(script);
scripts.add(script);
}
return scripts;
}
/** This code is needed to set Script.file in earlier installations.
* @deprecated remove before the next stable release! */
private void fixUnsetFile(Script script) {
if (script.file == null)
script.file = new File(ScriptingEngine.getUserScriptDir(), script.name);
}
public static ExecutionMode parseExecutionMode(final String executionModeString) {
try {
return ExecutionMode.valueOf(executionModeString.toUpperCase());
}
catch (Exception e) {
throw new RuntimeException("invalid execution mode found in " + executionModeString, e);
}
}
public List<Script> getScripts() {
return scripts;
}
public static String getNameKey(final String name) {
return "addons." + name;
}
public XMLElement toXml() {
final XMLElement xmlElement = super.toXml();
addScriptsAsChild(xmlElement);
return xmlElement;
}
private void addScriptsAsChild(XMLElement parent) {
XMLElement xmlElement = new XMLElement("scripts");
for (Script script : scripts) {
XMLElement scriptXmlElement = new XMLElement("script");
scriptXmlElement.setAttribute("name", script.name);
scriptXmlElement.setAttribute("file", script.file == null ? null : script.file.getPath());
scriptXmlElement.setAttribute("menuTitleKey", script.menuTitleKey);
scriptXmlElement.setAttribute("menuLocation", script.menuLocation);
scriptXmlElement.setAttribute("executionMode", script.executionMode.toString());
final List<String> permissionNames = ScriptingPermissions.getPermissionNames();
for (String permission : permissionNames) {
scriptXmlElement.setAttribute(permission, Boolean.toString(script.permissions.get(permission)));
}
xmlElement.addChild(scriptXmlElement);
}
parent.addChild(xmlElement);
}
@Override
public boolean supportsOperation(String opName) {
if (opName.equals(OP_DEACTIVATE))
return isActive() && !scripts.isEmpty();
return super.supportsOperation(opName);
}
}