blob: 484feac5dcded9dbb8322977805a6248e538651e [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.activities.wsdl.actions;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import net.sf.taverna.t2.activities.wsdl.servicedescriptions.WSDLServiceDescription;
import net.sf.taverna.t2.activities.wsdl.xmlsplitter.XMLSplitterConfigurationBeanBuilder;
import net.sf.taverna.t2.workbench.edits.CompoundEdit;
import net.sf.taverna.t2.workbench.edits.Edit;
import net.sf.taverna.t2.workbench.edits.EditException;
import net.sf.taverna.t2.workflow.edits.AddChildEdit;
import net.sf.taverna.t2.workflow.edits.AddDataLinkEdit;
import net.sf.taverna.t2.workflow.edits.AddProcessorEdit;
import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
import net.sf.taverna.wsdl.parser.TypeDescriptor;
import net.sf.taverna.wsdl.xmlsplitter.XMLSplitterSerialisationHelper;
import org.jdom.Element;
import uk.org.taverna.scufl2.api.activity.Activity;
import uk.org.taverna.scufl2.api.common.Scufl2Tools;
import uk.org.taverna.scufl2.api.configurations.Configuration;
import uk.org.taverna.scufl2.api.core.DataLink;
import uk.org.taverna.scufl2.api.core.Processor;
import uk.org.taverna.scufl2.api.core.Workflow;
import uk.org.taverna.scufl2.api.iterationstrategy.CrossProduct;
import uk.org.taverna.scufl2.api.port.InputProcessorPort;
import uk.org.taverna.scufl2.api.port.OutputProcessorPort;
import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
import uk.org.taverna.scufl2.api.profiles.Profile;
import com.fasterxml.jackson.databind.JsonNode;
public class AddXMLSplitterEdit implements Edit<Workflow> {
public static final URI INPUT_SPLITTER_TYPE = URI
.create("http://ns.taverna.org.uk/2010/activity/xml-splitter/in");
public static final URI OUTPUT_SPLITTER_TYPE = URI
.create("http://ns.taverna.org.uk/2010/activity/xml-splitter/out");
public static final URI SPLITTER_CONFIG_TYPE = URI
.create("http://ns.taverna.org.uk/2010/activity/xml-splitter#Config");
private Scufl2Tools scufl2Tools = new Scufl2Tools();
private final Workflow workflow;
private final Profile profile;
private final Activity activity;
private TypeDescriptor typeDescriptor;
private final String portName;
private final boolean isInput;
private CompoundEdit compoundEdit1 = null;
private Edit<?> linkUpEdit;
private boolean applied = false;
public AddXMLSplitterEdit(Workflow workflow, Profile profile, Activity activity,
TypeDescriptor typeDescriptor, String portName, boolean isInput) {
this.workflow = workflow;
this.profile = profile;
this.activity = activity;
this.typeDescriptor = typeDescriptor;
this.portName = portName;
this.isInput = isInput;
}
@Override
public Workflow doEdit() throws EditException {
if (applied) {
throw new EditException("Edit has already been applied!");
}
Activity splitter = null;
Configuration splitterConfiguration = null;
String sourcePortName = "";
Processor sourceProcessor = null;
String sinkPortName = "";
Processor sinkProcessor = null;
Processor activityProcessor = null;
List<ProcessorBinding> processorBindingsToActivity = scufl2Tools
.processorBindingsToActivity(activity);
for (ProcessorBinding processorBinding : processorBindingsToActivity) {
activityProcessor = processorBinding.getBoundProcessor();
break;
}
if (activityProcessor == null) {
throw new EditException("Cannot find the processor that the activity belongs to");
}
String displayName = portName;
if (portName.equals("parameters")) {
displayName = isInput ? "input" : "output";
}
String processorName = activityProcessor.getName();
String candidateName;
if (displayName.startsWith(processorName)) {
// No need to make GetRequest_GetRequestResponse
candidateName = displayName;
} else {
// Combine with processor name
String displayProcessorName;
if (activity.getType().equals(INPUT_SPLITTER_TYPE)
|| activity.getType().equals(OUTPUT_SPLITTER_TYPE)) {
// For splitters on splitters - avoid adding up blah_bluh_blih_more_stuff
String[] processorNameSplit = processorName.replace("_input", "")
.replace("_output", "").split("_");
displayProcessorName = processorNameSplit[processorNameSplit.length - 1];
} else {
displayProcessorName = activityProcessor.getName();
}
candidateName = displayProcessorName + "_" + displayName;
}
Processor splitterProcessor = new Processor();
splitterProcessor.setName(candidateName);
CrossProduct crossProduct = new CrossProduct();
crossProduct.setParent(splitterProcessor.getIterationStrategyStack());
ProcessorBinding processorBinding = new ProcessorBinding();
processorBinding.setBoundProcessor(splitterProcessor);
try {
if (activity.getType().equals(INPUT_SPLITTER_TYPE)) {
if (!isInput) {
throw new EditException(
"Can only add an input splitter to another input splitter");
}
if (typeDescriptor instanceof ArrayTypeDescriptor
&& !((ArrayTypeDescriptor) typeDescriptor).isWrapped()) {
typeDescriptor = ((ArrayTypeDescriptor) typeDescriptor).getElementType();
}
Element element = XMLSplitterSerialisationHelper
.typeDescriptorToExtensionXML(typeDescriptor);
// String wrappedType = new XMLOutputter().outputString(element);
splitter = new Activity();
splitter.setType(INPUT_SPLITTER_TYPE);
splitterConfiguration = new Configuration();
splitterConfiguration.setType(SPLITTER_CONFIG_TYPE);
splitterConfiguration.setConfigures(splitter);
// ((ObjectNode) splitterConfiguration.getJson()).put("wrappedType", wrappedType);
JsonNode bean = XMLSplitterConfigurationBeanBuilder.buildBeanForInput(element);
splitterConfiguration.setJson(bean);
XMLSplitterPortBuilder.addPortsForInput(element, splitter, splitterProcessor,
processorBinding);
} else if (activity.getType().equals(OUTPUT_SPLITTER_TYPE)) {
if (isInput) {
throw new EditException(
"Can only add an output splitter to another output splitter");
}
if (typeDescriptor instanceof ArrayTypeDescriptor
&& !((ArrayTypeDescriptor) typeDescriptor).isWrapped()) {
typeDescriptor = ((ArrayTypeDescriptor) typeDescriptor).getElementType();
}
Element element = XMLSplitterSerialisationHelper
.typeDescriptorToExtensionXML(typeDescriptor);
// String wrappedType = new XMLOutputter().outputString(element);
splitter = new Activity();
splitter.setType(OUTPUT_SPLITTER_TYPE);
splitterConfiguration = new Configuration();
splitterConfiguration.setType(SPLITTER_CONFIG_TYPE);
splitterConfiguration.setConfigures(splitter);
// ((ObjectNode) splitterConfiguration.getJson()).put("wrappedType", wrappedType);
JsonNode bean = XMLSplitterConfigurationBeanBuilder.buildBeanForOutput(element);
splitterConfiguration.setJson(bean);
XMLSplitterPortBuilder.addPortsForOutput(element, splitter, splitterProcessor,
processorBinding);
} else if (activity.getType().equals(WSDLServiceDescription.ACTIVITY_TYPE)) {
if (isInput) {
Element element = XMLSplitterSerialisationHelper
.typeDescriptorToExtensionXML(typeDescriptor);
// String wrappedType = new XMLOutputter().outputString(element);
splitter = new Activity();
splitter.setType(WSDLServiceDescription.INPUT_SPLITTER_TYPE);
splitterConfiguration = new Configuration();
splitterConfiguration.setType(SPLITTER_CONFIG_TYPE);
splitterConfiguration.setConfigures(splitter);
// ((ObjectNode) splitterConfiguration.getJson()).put("wrappedType", wrappedType);
JsonNode bean = XMLSplitterConfigurationBeanBuilder.buildBeanForInput(element);
splitterConfiguration.setJson(bean);
XMLSplitterPortBuilder.addPortsForInput(element, splitter, splitterProcessor,
processorBinding);
} else {
Element element = XMLSplitterSerialisationHelper
.typeDescriptorToExtensionXML(typeDescriptor);
// String wrappedType = new XMLOutputter().outputString(element);
splitter = new Activity();
splitter.setType(WSDLServiceDescription.OUTPUT_SPLITTER_TYPE);
splitterConfiguration = new Configuration();
splitterConfiguration.setType(SPLITTER_CONFIG_TYPE);
splitterConfiguration.setConfigures(splitter);
// ((ObjectNode) splitterConfiguration.getJson()).put("wrappedType", wrappedType);
JsonNode bean = XMLSplitterConfigurationBeanBuilder.buildBeanForOutput(element);
splitterConfiguration.setJson(bean);
XMLSplitterPortBuilder.addPortsForOutput(element, splitter, splitterProcessor,
processorBinding);
}
} else {
throw new EditException(
"The activity type is not suitable for adding xml processing processors");
}
} catch (Exception e) {
throw new EditException(
"An error occured whilst tyring to add an XMLSplitter to the activity:"
+ activity, e);
}
if (isInput) {
sourcePortName = "output";
sinkPortName = portName;
sinkProcessor = activityProcessor;
sourceProcessor = splitterProcessor;
} else {
sourcePortName = portName;
sinkPortName = "input";
sinkProcessor = splitterProcessor;
sourceProcessor = activityProcessor;
}
processorBinding.setBoundActivity(splitter);
List<Edit<?>> editList = new ArrayList<Edit<?>>();
editList.add(new AddChildEdit<Profile>(profile, splitter));
editList.add(new AddChildEdit<Profile>(profile, splitterConfiguration));
editList.add(new AddChildEdit<Profile>(profile, processorBinding));
editList.add(new AddProcessorEdit(workflow, splitterProcessor));
compoundEdit1 = new CompoundEdit(editList);
compoundEdit1.doEdit();
List<Edit<?>> linkUpEditList = new ArrayList<Edit<?>>();
OutputProcessorPort source = sourceProcessor.getOutputPorts().getByName(sourcePortName);
InputProcessorPort sink = sinkProcessor.getInputPorts().getByName(sinkPortName);
if (source == null)
throw new EditException("Unable to find the source port when linking up "
+ sourcePortName + " to " + sinkPortName);
if (sink == null)
throw new EditException("Unable to find the sink port when linking up "
+ sourcePortName + " to " + sinkPortName);
DataLink dataLink = new DataLink();
dataLink.setReceivesFrom(source);
dataLink.setSendsTo(sink);
linkUpEditList.add(new AddDataLinkEdit(workflow, dataLink));
linkUpEdit = new CompoundEdit(linkUpEditList);
linkUpEdit.doEdit();
applied = true;
return workflow;
}
@Override
public void undo() {
if (!applied) {
throw new RuntimeException("Attempt to undo edit that was never applied");
}
if (linkUpEdit.isApplied())
linkUpEdit.undo();
if (compoundEdit1.isApplied())
compoundEdit1.undo();
applied = false;
}
@Override
public boolean isApplied() {
return applied;
}
@Override
public Object getSubject() {
return workflow;
}
}