blob: 1386b45c32360278621edb02ebac47bf826292bc [file] [log] [blame]
package org.apache.taverna.scufl2.rdfxml;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.apache.taverna.scufl2.api.activity.Activity;
import org.apache.taverna.scufl2.api.common.Configurable;
import org.apache.taverna.scufl2.api.container.WorkflowBundle;
import org.apache.taverna.scufl2.api.core.Processor;
import org.apache.taverna.scufl2.api.io.ReaderException;
import org.apache.taverna.scufl2.api.port.InputActivityPort;
import org.apache.taverna.scufl2.api.port.InputProcessorPort;
import org.apache.taverna.scufl2.api.port.OutputActivityPort;
import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
import org.apache.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.apache.taverna.scufl2.xml.Configuration;
import org.apache.taverna.scufl2.xml.ProcessorBinding.InputPortBinding;
import org.apache.taverna.scufl2.xml.ProcessorBinding.OutputPortBinding;
import org.apache.taverna.scufl2.xml.Profile;
import org.apache.taverna.scufl2.xml.ProfileDocument;
public class ProfileParser extends AbstractParser {
private static Logger logger = Logger.getLogger(ProfileParser.class
.getCanonicalName());
public ProfileParser() {
super();
}
public ProfileParser(ThreadLocal<ParserState> parserState) {
super(parserState);
}
@SuppressWarnings("unused")
private Element getChildElement(Element element) {
for (Node node : nodeIterable(element.getChildNodes()))
if (node instanceof Element)
return (Element) node;
return null;
}
private Iterable<Node> nodeIterable(final NodeList childNodes) {
return new Iterable<Node>() {
@Override
public Iterator<Node> iterator() {
return new Iterator<Node>() {
int position = 0;
@Override
public boolean hasNext() {
return childNodes.getLength() > position;
}
@Override
public Node next() {
return childNodes.item(position++);
}
@Override
public void remove() {
Node node = childNodes.item(position);
node.getParentNode().removeChild(node);
}
};
}
};
}
protected void parseActivity(
org.apache.taverna.scufl2.xml.Activity original) {
Activity activity = new Activity();
getParserState().push(activity);
try {
mapBean(original.getAbout(), activity);
if (original.getName() != null)
activity.setName(original.getName());
activity.setParent(getParserState().getCurrent(
org.apache.taverna.scufl2.api.profiles.Profile.class));
if (original.getType() != null)
activity.setType(resolve(original.getType().getResource()));
for (org.apache.taverna.scufl2.xml.Activity.InputActivityPort inputActivityPort : original
.getInputActivityPort())
parseInputActivityPort(inputActivityPort.getInputActivityPort());
for (org.apache.taverna.scufl2.xml.Activity.OutputActivityPort outputActivityPort : original
.getOutputActivityPort())
parseOutputActivityPort(outputActivityPort
.getOutputActivityPort());
} finally {
getParserState().pop();
}
}
private static final URI INTERNAL_DISPATCH_PREFIX = URI.create("http://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/");
protected void parseConfiguration(Configuration original)
throws ReaderException {
org.apache.taverna.scufl2.api.configurations.Configuration config = new org.apache.taverna.scufl2.api.configurations.Configuration();
boolean ignoreConfig = false;
if (original.getType() != null) {
URI type = resolve(original.getType().getResource());
if (! INTERNAL_DISPATCH_PREFIX.relativize(type).isAbsolute()) {
logger.fine("Ignoring unsupported Dispatch stack configuration (SCUFL2-130)");
logger.finest(original.getAbout());
ignoreConfig = true;
}
config.setType(type);
}
if (original.getName() != null)
config.setName(original.getName());
if (!ignoreConfig) {
mapBean(original.getAbout(), config);
if (original.getConfigure() != null) {
Configurable configurable = resolveBeanUri(original
.getConfigure().getResource(), Configurable.class);
config.setConfigures(configurable);
}
config.setParent(getParserState().getCurrent(
org.apache.taverna.scufl2.api.profiles.Profile.class));
}
getParserState().push(config);
if (original.getSeeAlso() != null) {
String about = original.getSeeAlso().getResource();
if (about != null) {
URI resource = resolve(about);
URI bundleBase = parserState .get().getLocation();
URI path = uriTools.relativePath(bundleBase, resource);
if (ignoreConfig) {
logger.finest("Deleting " + path + " (SCUFL2-130)");
parserState.get().getUcfPackage().removeResource(path.getRawPath());
} else {
try {
// TODO: Should the path in the UCF Package be %-escaped or not?
// See TestRDFXMLWriter.awkwardFilenames
config.setJson(parserState.get().getUcfPackage().getResourceAsString(path.getRawPath()));
} catch (IllegalArgumentException e) {
logger.log(Level.WARNING, "Could not parse JSON configuration " + path, e);
} catch (IOException e) {
logger.log(Level.WARNING, "Could not load JSON configuration " + path, e);
}
}
}
}
for (Object o : original.getAny()) {
// Legacy SCUFL2 <= 0.11.0 PropertyResource configuration
// Just ignoring it for now :(
//
// TODO: Parse and represent as JSON-LD?
logger.warning("Ignoring unsupported PropertyResource (from wfbundle 0.2.0 or older) for " + config + " " + o);
}
getParserState().pop();
}
protected void parseInputActivityPort(
org.apache.taverna.scufl2.xml.InputActivityPort original) {
InputActivityPort port = new InputActivityPort();
mapBean(original.getAbout(), port);
port.setParent(getParserState().getCurrent(Activity.class));
port.setName(original.getName());
if (original.getPortDepth() != null)
port.setDepth(original.getPortDepth().getValue());
}
protected void parseInputPortBinding(
org.apache.taverna.scufl2.xml.InputPortBinding original)
throws ReaderException {
ProcessorInputPortBinding binding = new ProcessorInputPortBinding();
mapBean(original.getAbout(), binding);
binding.setBoundActivityPort(resolveBeanUri(original
.getBindInputActivityPort().getResource(),
InputActivityPort.class));
binding.setBoundProcessorPort(resolveBeanUri(original
.getBindInputProcessorPort().getResource(),
InputProcessorPort.class));
binding.setParent(getParserState().getCurrent(ProcessorBinding.class));
}
protected void parseOutputActivityPort(
org.apache.taverna.scufl2.xml.OutputActivityPort original) {
OutputActivityPort port = new OutputActivityPort();
mapBean(original.getAbout(), port);
port.setParent(getParserState().getCurrent(Activity.class));
port.setName(original.getName());
if (original.getPortDepth() != null)
port.setDepth(original.getPortDepth().getValue());
if (original.getGranularPortDepth() != null)
port.setGranularDepth(original.getGranularPortDepth().getValue());
}
protected void parseOutputPortBinding(
org.apache.taverna.scufl2.xml.OutputPortBinding original)
throws ReaderException {
ProcessorOutputPortBinding binding = new ProcessorOutputPortBinding();
mapBean(original.getAbout(), binding);
binding.setBoundActivityPort(resolveBeanUri(original
.getBindOutputActivityPort().getResource(),
OutputActivityPort.class));
binding.setBoundProcessorPort(resolveBeanUri(original
.getBindOutputProcessorPort().getResource(),
OutputProcessorPort.class));
binding.setParent(getParserState().getCurrent(ProcessorBinding.class));
}
protected void parseProcessorBinding(
org.apache.taverna.scufl2.xml.ProcessorBinding original)
throws ReaderException {
org.apache.taverna.scufl2.api.profiles.ProcessorBinding binding = new org.apache.taverna.scufl2.api.profiles.ProcessorBinding();
binding.setParent(getParserState().getCurrent(
org.apache.taverna.scufl2.api.profiles.Profile.class));
mapBean(original.getAbout(), binding);
getParserState().push(binding);
if (original.getName() != null)
binding.setName(original.getName());
if (original.getActivityPosition() != null)
binding.setActivityPosition(original.getActivityPosition()
.getValue());
URI processorUri = resolve(original.getBindProcessor().getResource());
URI activityUri = resolve(original.getBindActivity().getResource());
binding.setBoundProcessor((Processor) resolveBeanUri(processorUri));
binding.setBoundActivity((Activity) resolveBeanUri(activityUri));
for (InputPortBinding inputPortBinding : original.getInputPortBinding())
parseInputPortBinding(inputPortBinding.getInputPortBinding());
for (OutputPortBinding outputPortBinding : original
.getOutputPortBinding())
parseOutputPortBinding(outputPortBinding.getOutputPortBinding());
getParserState().pop();
}
protected void parseProfile(Profile original, URI profileUri) {
org.apache.taverna.scufl2.api.profiles.Profile p = new org.apache.taverna.scufl2.api.profiles.Profile();
p.setParent(getParserState().getCurrent(WorkflowBundle.class));
getParserState().push(p);
if (original.getAbout() != null) {
URI about = getParserState().getCurrentBase().resolve(
original.getAbout());
mapBean(about, p);
} else
mapBean(profileUri, p);
if (original.getName() != null)
p.setName(original.getName());
// Note - we'll pop() in profileSecond() instead
}
protected void parseProfileSecond(Profile profileElem) {
// TODO: Parse activates config etc.
getParserState().pop();
}
protected void readProfile(URI profileUri, URI source)
throws ReaderException, IOException {
if (source.isAbsolute())
throw new ReaderException("Can't read external profile source "
+ source);
InputStream bundleStream = getParserState().getUcfPackage()
.getResourceAsInputStream(source.getRawPath());
if (bundleStream == null)
throw new ReaderException("Can't find profile " + source.getPath());
readProfile(profileUri, source, bundleStream);
}
@SuppressWarnings("unchecked")
protected void readProfile(URI profileUri, URI source,
InputStream bundleStream) throws ReaderException, IOException {
JAXBElement<ProfileDocument> elem;
try {
elem = (JAXBElement<ProfileDocument>) unmarshaller
.unmarshal(bundleStream);
} catch (JAXBException e) {
throw new ReaderException("Can't parse profile document " + source,
e);
}
URI base = getParserState().getLocation().resolve(source);
if (elem.getValue().getBase() != null)
base = base.resolve(elem.getValue().getBase());
getParserState().setCurrentBase(base);
org.apache.taverna.scufl2.xml.Profile profileElem = null;
for (Object any : elem.getValue().getAny())
if (any instanceof org.apache.taverna.scufl2.xml.Profile) {
if (profileElem != null)
throw new ReaderException("More than one <Profile> found");
profileElem = (org.apache.taverna.scufl2.xml.Profile) any;
parseProfile(profileElem, profileUri);
} else if (any instanceof org.apache.taverna.scufl2.xml.Activity) {
if (profileElem == null)
throw new ReaderException("No <Profile> found");
parseActivity((org.apache.taverna.scufl2.xml.Activity) any);
} else if (any instanceof org.apache.taverna.scufl2.xml.ProcessorBinding) {
if (profileElem == null)
throw new ReaderException("No <Profile> found");
parseProcessorBinding((org.apache.taverna.scufl2.xml.ProcessorBinding) any);
} else if (any instanceof org.apache.taverna.scufl2.xml.Configuration) {
if (profileElem == null)
throw new ReaderException("No <Profile> found");
parseConfiguration((org.apache.taverna.scufl2.xml.Configuration) any);
}
parseProfileSecond(profileElem);
}
}