/*
* Copyright (c) 2009/2010, IETR/INSA of Rennes
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the IETR/INSA of Rennes nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package net.sf.orcc.plugins;
import static net.sf.orcc.OrccActivator.PLUGIN_ID;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import net.sf.orcc.plugins.impl.ComboboxItemImpl;
import net.sf.orcc.plugins.impl.OptionBrowseFileImpl;
import net.sf.orcc.plugins.impl.OptionCheckboxImpl;
import net.sf.orcc.plugins.impl.OptionComboboxImpl;
import net.sf.orcc.plugins.impl.OptionSelectNetworkImpl;
import net.sf.orcc.plugins.impl.OptionSelectNetworksImpl;
import net.sf.orcc.plugins.impl.OptionTextBoxImpl;
import net.sf.orcc.plugins.impl.PluginOptionImpl;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
/**
* A factory class that contains a list of plugins and their options. The
* plugins are classes that implement either the {@link Backend} or the
* {@link Simulator} interface and are declared in either the
* <code>net.sf.orcc.plugin.backend</code> or the
* <code>net.sf.orcc.plugin.simulator</code> extension point.
*
* @author Matthieu Wipliez
* @author Jerome Gorin
* @author Herve Yviquel
*
*/
public class PluginFactory {
/**
* list of options.
*/
protected Map<String, Option> options;
/**
* list of options of a plugin.
*/
protected Map<String, List<Option>> pluginOptions;
/**
* list of plugins.
*/
protected final Map<String, Object> plugins;
private IConfigurationElement[] elements;
protected PluginFactory() {
plugins = new TreeMap<String, Object>();
pluginOptions = new HashMap<String, List<Option>>();
options = new HashMap<String, Option>();
IExtensionRegistry registry = Platform.getExtensionRegistry();
elements = registry.getConfigurationElementsFor(PLUGIN_ID + ".options");
parseOptions(elements);
}
/**
* Returns the list of options associated to the plugin with the given name.
*
* @return associated to the plugin
*/
public List<Option> getOptions(String name) {
return pluginOptions.get(name);
}
/**
* Returns the list of the names of registered backend or simulator plugins
*
* @return the list of the names of registered backend or simulator plugins
*/
public List<String> listPlugins() {
return new ArrayList<String>(plugins.keySet());
}
/**
* Parses the given configuration element as an "input file" option.
*
* @param element
* a configuration element
* @return an "input file" option
*/
private OptionBrowseFile parseBrowseFile(IConfigurationElement element) {
String extension = element.getAttribute("extension");
OptionBrowseFile option = new OptionBrowseFileImpl();
option.setExtension(extension);
String folder = element.getAttribute("folder");
option.setFolder(Boolean.parseBoolean(folder));
String workspace = element.getAttribute("workspace");
option.setWorkspace(Boolean.parseBoolean(workspace));
String optional = element.getAttribute("optional");
option.setOptional(Boolean.parseBoolean(optional));
return option;
}
/**
* Parses the given configuration element as a "checkbox" option.
*
* @param element
* a configuration element
* @return a "checkbox" option
*/
private OptionCheckbox parseCheckbox(IConfigurationElement element) {
OptionCheckbox option = new OptionCheckboxImpl();
List<Option> options = parseOptions(element.getChildren());
option.getOptions().addAll(options);
return option;
}
/**
* t Parses the given configuration element as a "combobox" option.
*
* @param element
* a configuration element
* @return a "combobox" option
*/
private OptionComboBox parseCombobox(IConfigurationElement element) {
OptionComboBox option = new OptionComboboxImpl();
List<ComboBoxItem> items = parseItems(element.getChildren());
option.getComboBoxItems().addAll(items);
return option;
}
private List<ComboBoxItem> parseItems(IConfigurationElement[] elements) {
List<ComboBoxItem> items = new ArrayList<ComboBoxItem>();
for (IConfigurationElement element : elements) {
ComboboxItemImpl comboBoxItem = new ComboboxItemImpl();
// Parse id of combo item
String id = element.getAttribute("id");
comboBoxItem.setId(id);
// Parse children options of comboBox
List<Option> options = parseOptions(element.getChildren());
comboBoxItem.getOptions().addAll(options);
items.add(comboBoxItem);
}
return items;
}
/**
* Parses the given configuration elements as a list of options. The options
* are added to the option map of this factory.
*
* @param elements
* a list of configuration elements
*/
protected List<Option> parseOptions(IConfigurationElement[] elements) {
List<Option> optionList = new ArrayList<Option>();
for (IConfigurationElement element : elements) {
if ("option".equals(element.getName())) {
Option option = parseOption(element);
optionList.add(option);
} else if ("optionRef".equals(element.getName())) {
String id = element.getAttribute("id");
Option option = options.get(id);
if (option == null) {
option = parseOption(id);
}
optionList.add(option);
}
}
return optionList;
}
/**
* Parses an option with the given id. I know that this is a horrible way of
* handling cross-referencing options, hopefully at some point someone will
* do better.
*
* @param id
* @return
*/
private Option parseOption(String id) {
for (IConfigurationElement element : elements) {
if (id.equals(element.getAttribute("id"))) {
return parseOption(element);
}
}
return null;
}
private Option parseOption(IConfigurationElement element) {
Option option;
String id = element.getAttribute("id");
String name = element.getAttribute("name");
IConfigurationElement[] children = element.getChildren();
if (children.length > 0) {
IConfigurationElement child = children[0];
String type = child.getName();
if (type.equals("browseFile")) {
option = parseBrowseFile(child);
} else if (type.equals("checkBox")) {
option = parseCheckbox(child);
} else if (type.equals("comboBox")) {
option = parseCombobox(child);
} else if (type.equals("selectNetwork")) {
option = new OptionSelectNetworkImpl();
} else if (type.equals("selectNetworks")) {
option = new OptionSelectNetworksImpl();
} else if (type.equals("textBox")) {
option = parseTexbox(child);
} else {
return null;
}
} else {
if ((id.equals("net.sf.orcc.plugins.backends.deactivateFE"))
|| (id.equals("net.sf.orcc.plugins.simulators.deactivateFE"))) {
option = new PluginOptionImpl();
} else {
return null;
}
}
option.setIdentifier(id);
option.setName(name);
String defaultValue = element.getAttribute("defaultValue");
if (defaultValue == null) {
defaultValue = "";
}
option.setDefaultValue(defaultValue);
String description = element.getAttribute("description");
if (description == null) {
description = "";
}
option.setDescription(description);
options.put(option.getIdentifier(), option);
return option;
}
/**
* Returns the list of options referenced by the list of "option" elements.
*
* @param elements
* a list of "option" elements
* @return a list of options
*/
private List<Option> parsePluginOptions(IConfigurationElement[] elements) {
List<Option> pluginOptions = new ArrayList<Option>();
for (IConfigurationElement element : elements) {
String id = element.getAttribute("id");
Option option = options.get(id);
pluginOptions.add(option);
}
return pluginOptions;
}
/**
* Parses the "plugin" elements as plugins.
*
* @param elements
* a list of "plugin" elements
*/
protected void parsePlugins(IConfigurationElement[] elements) {
for (IConfigurationElement element : elements) {
String name = element.getAttribute("name");
IConfigurationElement[] optionLists = element.getChildren();
List<Option> options = parsePluginOptions(optionLists);
this.pluginOptions.put(name, options);
try {
Object obj = element.createExecutableExtension("class");
plugins.put(name, obj);
} catch (CoreException e) {
e.printStackTrace();
}
}
}
/**
* Parses the given configuration element as a "textbox" option.
*
* @param element
* a configuration element
* @return a "textbox" option
*/
private OptionTextBox parseTexbox(IConfigurationElement element) {
OptionTextBox option = new OptionTextBoxImpl();
List<Option> options = parseOptions(element.getChildren());
option.getOptions().addAll(options);
return option;
}
}