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); } }