blob: af189382ff4fa7e752ad16a77055fbe3319e33f3 [file] [log] [blame]
/**
*
*/
package net.sf.taverna.t2.activities.externaltool.manager.impl;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.sf.taverna.t2.activities.externaltool.local.ExternalToolLocalInvocationMechanism;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroup;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroupAddedEvent;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroupChangedEvent;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroupManager;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroupRemovedEvent;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationManagerEvent;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanism;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanismAddedEvent;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanismChangedEvent;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanismRemovedEvent;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationPersister;
import net.sf.taverna.t2.activities.externaltool.manager.MechanismCreator;
import net.sf.taverna.t2.lang.observer.MultiCaster;
import net.sf.taverna.t2.lang.observer.Observable;
import net.sf.taverna.t2.lang.observer.Observer;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import uk.org.taverna.configuration.app.ApplicationConfiguration;
/**
* @author alanrw
*
*/
public class InvocationGroupManagerImpl implements Observable<InvocationManagerEvent>, InvocationGroupManager{
private static final String DEFAULT_MECHANISM_NAME = "default local";
private static final String DEFAULT_GROUP_NAME = "default";
private HashSet<InvocationGroup> groups = new HashSet<InvocationGroup>();
private InvocationGroup defaultGroup = null;
private HashSet<InvocationMechanism> mechanisms = new HashSet<InvocationMechanism>();
private static XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
private static SAXBuilder builder = new SAXBuilder();
private static Logger logger = Logger.getLogger(InvocationGroupManagerImpl.class);
private Map<InvocationGroup, InvocationGroup> groupReplacements = Collections.synchronizedMap(new HashMap<InvocationGroup, InvocationGroup>());
private Map<String, InvocationMechanism> mechanismReplacements = Collections.synchronizedMap(new HashMap<String, InvocationMechanism>());
private Map<String, InvocationGroup> groupImports = Collections.synchronizedMap(new HashMap<String, InvocationGroup> ());
private Map<String, InvocationMechanism> mechanismImports = Collections.synchronizedMap(new HashMap<String, InvocationMechanism> ());
private final ApplicationConfiguration applicationConfiguration;
private final List<MechanismCreator> mechanismCreators;
private final List<InvocationPersister> invocationPersisters;
protected MultiCaster<InvocationManagerEvent> observers = new MultiCaster<InvocationManagerEvent>(
this);
private InvocationMechanism defaultMechanism = null;
public InvocationGroupManagerImpl(ApplicationConfiguration applicationConfiguration, List<MechanismCreator> mechanismCreators, List<InvocationPersister> invocationPersisters) {
this.applicationConfiguration = applicationConfiguration;
this.mechanismCreators = mechanismCreators;
this.invocationPersisters = invocationPersisters;
readConfiguration();
defaultMechanism = getInvocationMechanism(DEFAULT_MECHANISM_NAME);
if (defaultMechanism == null) {
createDefaultMechanism();
}
defaultGroup = getInvocationGroup(DEFAULT_GROUP_NAME);
if (defaultGroup == null) {
createDefaultGroup();
}
saveConfiguration();
}
@Override
public void addInvocationGroup(InvocationGroup group) {
groups.add(group);
observers.notify(new InvocationGroupAddedEvent(group));
}
@Override
public void replaceInvocationGroup(InvocationGroup originalGroup, InvocationGroup replacementGroup) {
Set<String> toReplaceImports = new HashSet<String>();
for (Entry<String, InvocationGroup> entry : groupImports.entrySet()) {
if (entry.getValue() == originalGroup) {
toReplaceImports.add(entry.getKey());
}
}
for (String spec : toReplaceImports) {
if (replacementGroup == null) {
groupImports.remove(spec);
} else {
groupImports.put(spec, replacementGroup);
}
}
if (replacementGroup != null) {
groupReplacements.put(originalGroup, replacementGroup);
}
observers.notify(new InvocationGroupRemovedEvent(originalGroup, (replacementGroup == null? getDefaultGroup(): replacementGroup)));
}
@Override
public void removeInvocationGroup(InvocationGroup group) {
groups.remove(group);
replaceInvocationGroup(group, getDefaultGroup());
}
@Override
public void replaceInvocationMechanism(InvocationMechanism originalMechanism, InvocationMechanism replacementMechanism) {
for (InvocationGroup g : groups) {
if (g.getMechanism().equals(originalMechanism)) {
if (replacementMechanism == null) {
g.setMechanism(getDefaultMechanism());
} else {
g.setMechanism(replacementMechanism);
}
}
}
Set<String> toRemoveImports = new HashSet<String>();
for (Entry<String, InvocationMechanism> entry : mechanismImports.entrySet()) {
if (entry.getValue() == originalMechanism) {
toRemoveImports.add(entry.getKey());
}
}
for (String spec : toRemoveImports) {
if (replacementMechanism == null) {
mechanismImports.remove(spec);
} else {
mechanismImports.put(spec, replacementMechanism);
}
}
if (replacementMechanism != null) {
mechanismReplacements.put(originalMechanism.getName() + ":" + originalMechanism.getXML(), replacementMechanism);
}
observers.notify(new InvocationMechanismRemovedEvent(originalMechanism, (replacementMechanism == null? getDefaultMechanism(): replacementMechanism)));
}
@Override
public void removeMechanism(InvocationMechanism mechanism) {
mechanisms.remove(mechanism);
replaceInvocationMechanism(mechanism, getDefaultMechanism());
}
@Override
public HashSet<InvocationGroup> getInvocationGroups() {
return groups;
}
@Override
public InvocationGroup getDefaultGroup() {
if (defaultGroup == null) {
createDefaultGroup();
}
return defaultGroup;
}
@Override
public Set<InvocationMechanism> getMechanisms() {
return mechanisms;
}
@Override
public void addMechanism(InvocationMechanism mechanism) {
mechanisms.add(mechanism);
observers.notify(new InvocationMechanismAddedEvent(mechanism));
}
@Override
public InvocationMechanism getDefaultMechanism() {
if (defaultMechanism == null) {
createDefaultMechanism();
}
return defaultMechanism;
}
@Override
public boolean containsGroup(InvocationGroup group) {
return groups.contains(group);
}
@Override
public InvocationMechanism getInvocationMechanism(
String defaultMechanismName) {
for (InvocationMechanism m : mechanisms) {
if (m.getName().equals(defaultMechanismName)) {
return m;
}
}
return null;
}
InvocationGroup getInvocationGroup(String groupName) {
for (InvocationGroup g : groups) {
if (g.getName().equals(groupName)) {
return g;
}
}
return null;
}
@Override
public void mechanismChanged(InvocationMechanism im) {
observers.notify(new InvocationMechanismChangedEvent(im));
}
private void createDefaultMechanism() {
defaultMechanism = new ExternalToolLocalInvocationMechanism();
defaultMechanism.setName(DEFAULT_MECHANISM_NAME);
mechanisms.add(defaultMechanism);
}
private void createDefaultGroup() {
defaultGroup = new InvocationGroup(mechanismCreators);
defaultGroup.setName(DEFAULT_GROUP_NAME);
defaultGroup.setMechanism(defaultMechanism);
groups.add(defaultGroup);
}
private void readConfiguration() {
File f = new File(getInvocationManagerDirectory(), "invocationManager.xml");
if (!f.exists()) {
return;
}
try {
Document document = null;
synchronized (builder) {
document = builder.build(f);
}
Element topElement = document.getRootElement();
Element mechanismsElement = topElement.getChild("invocationMechanisms");
for (Object mechanismObject : mechanismsElement.getChildren("invocationMechanism")) {
Element mechanismElement = (Element) mechanismObject;
Element mechanismNameElement = mechanismElement.getChild("invocationMechanismName");
String mechanismName = mechanismNameElement.getText();
Element mechanismTypeElement = mechanismElement.getChild("invocationMechanismType");
String mechanismType = mechanismTypeElement.getText();
Element mechanismDetailsElement = mechanismElement.getChild("mechanismDetails");
Element detailsElement = (Element) mechanismDetailsElement.getChildren().get(0);
InvocationMechanism mechanism = null;
for (MechanismCreator mc : mechanismCreators) {
if (mc.canHandle(mechanismType)) {
mechanism = mc.convert(detailsElement, mechanismName);
}
}
if (mechanism != null) {
this.addMechanism(mechanism);
}
}
Element groupsElement = topElement.getChild("invocationGroups");
for (Object groupObject : groupsElement.getChildren("invocationGroup")) {
Element groupElement = (Element) groupObject;
Element groupNameElement = groupElement.getChild("invocationGroupName");
String groupName = groupNameElement.getText();
Element mechanismNameElement = groupElement.getChild("mechanismName");
String mechanismName = mechanismNameElement.getText();
InvocationMechanism mechanism = getInvocationMechanism(mechanismName);
if (mechanism == null) {
logger.warn("Could not find mechanism " + mechanismName);
mechanism = getDefaultMechanism();
}
InvocationGroup group = new InvocationGroup(mechanismCreators);
group.setName(groupName);
group.setMechanism(mechanism);
group.convertMechanismToDetails();
this.addInvocationGroup(group);
}
} catch (JDOMException e) {
logger.error("XML parsing problem", e);
} catch (IOException e) {
logger.error("Unable to read invocation manager", e);
}
}
/**
* Get the directory where the invocation information will be/is saved to.
*/
@Override
public File getInvocationManagerDirectory() {
File home = applicationConfiguration.getApplicationHomeDir();
File invocationManagerDirectory = new File(home,"externaltool");
if (!invocationManagerDirectory.exists()) {
invocationManagerDirectory.mkdir();
}
return invocationManagerDirectory;
}
@Override
public void saveConfiguration() {
File f = new File(getInvocationManagerDirectory(), "invocationManager.xml");
Document configDocument = new Document();
Element topElement = new Element("invocationManager");
Element mechanismsElement = new Element("invocationMechanisms");
for (InvocationMechanism m : mechanisms) {
Element mechanismElement = new Element("invocationMechanism");
Element nameElement = new Element("invocationMechanismName");
nameElement.setText(m.getName());
mechanismElement.addContent(nameElement);
Element typeElement = new Element("invocationMechanismType");
typeElement.setText(m.getType());
mechanismElement.addContent(typeElement);
Element mechanismDetails = new Element("mechanismDetails");
mechanismDetails.addContent(m.getXMLElement());
mechanismElement.addContent(mechanismDetails);
mechanismsElement.addContent(mechanismElement);
}
topElement.addContent(mechanismsElement);
Element groupsElement = new Element("invocationGroups");
for (InvocationGroup g : groups) {
Element groupElement = new Element("invocationGroup");
Element nameElement = new Element("invocationGroupName");
nameElement.setText(g.getName());
groupElement.addContent(nameElement);
Element mechanismNameElement = new Element("mechanismName");
mechanismNameElement.setText(g.getMechanism().getName());
groupElement.addContent(mechanismNameElement);
groupsElement.addContent(groupElement);
}
topElement.addContent(groupsElement);
configDocument.setRootElement(topElement);
FileWriter writer;
try {
writer = new FileWriter(f);
synchronized (outputter) {
outputter.output(configDocument, writer);
}
writer.close();
} catch (IOException e) {
logger.error("Unable to save invocation manager", e);
}
}
@Override
public void groupChanged(InvocationGroup group) {
observers.notify(new InvocationGroupChangedEvent(group));
}
@Override
public void addObserver(Observer<InvocationManagerEvent> observer) {
observers.addObserver(observer);
}
@Override
public List<Observer<InvocationManagerEvent>> getObservers() {
return observers.getObservers();
}
@Override
public void removeObserver(Observer<InvocationManagerEvent> observer) {
observers.removeObserver(observer);
}
@Override
public void deleteRun(String runId) {
for (InvocationPersister persister : invocationPersisters) {
persister.deleteRun(runId);
}
}
@Override
public void persistInvocations() {
for (InvocationPersister persister : invocationPersisters) {
persister.persist(getInvocationManagerDirectory());
}
}
@Override
public void loadInvocations() {
for (InvocationPersister persister : invocationPersisters) {
persister.load(getInvocationManagerDirectory());
}
}
@Override
public boolean containsMechanism(InvocationMechanism invocationMechanism) {
return mechanisms.contains(invocationMechanism);
}
@Override
public InvocationGroup getGroupReplacement(InvocationGroup group) {
return groupReplacements.get(group);
}
@Override
public InvocationMechanism getMechanismReplacement(String invocationMechanismSpecification) {
return mechanismReplacements.get(invocationMechanismSpecification);
}
@Override
public InvocationGroup getImportedGroup(String groupSpecification) {
return groupImports.get(groupSpecification);
}
@Override
public InvocationMechanism getImportedMechanism(String mechanismSpecification) {
return mechanismImports.get(mechanismSpecification);
}
@Override
public void importMechanism(String invocationMechanismSpecification,
InvocationMechanism createdMechanism) {
addMechanism(createdMechanism);
mechanismImports.put(invocationMechanismSpecification, createdMechanism);
}
@Override
public void importInvocationGroup(String invocationGroupSpecification,
InvocationGroup invocationGroup) {
addInvocationGroup(invocationGroup);
groupImports.put(invocationGroupSpecification, invocationGroup);
}
}