es.usc.citius.composit.transformer.wsc.wscxml.WSCTransformer.java Source code

Java tutorial

Introduction

Here is the source code for es.usc.citius.composit.transformer.wsc.wscxml.WSCTransformer.java

Source

/*
 * Copyright (c) 2013. Knowledge Media Institute - The Open University
 *
 * Licensed 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.
 */

package es.usc.citius.composit.transformer.wsc.wscxml;

import es.usc.citius.composit.transformer.wsc.wscxml.model.XMLInstance;
import es.usc.citius.composit.transformer.wsc.wscxml.model.services.XMLService;
import es.usc.citius.composit.transformer.wsc.wscxml.model.services.XMLServices;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import uk.ac.open.kmi.msm4j.*;
import uk.ac.open.kmi.msm4j.io.ServiceTransformer;
import uk.ac.open.kmi.msm4j.io.TransformationException;

import javax.xml.bind.JAXB;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Imports and transforms datasets from the Web Service Challenge 2008 (XML format)
 * Date: 7/18/13
 *
 * @author Pablo Rodrguez Mier
 */
public class WSCTransformer implements ServiceTransformer {

    private static final Logger log = LoggerFactory.getLogger(WSCTransformer.class);
    private WSCXMLSemanticReasoner reasoner;
    // Default name of the files for the taxonomy. These files must be in the same
    // directory as the service.xml file to auto-load them.
    private String taxonomyFile = "taxonomy.xml";
    private String ontologyFile = "taxonomy.owl";

    // This fake URL is replaced by iServe.
    private String fakeURL = "http://localhost/services/services.owl";

    // Mediatype of the WSC format
    public static final String mediaType = "text/xml";

    /**
     * The WSC specification does not define the ontology URI of the concepts.
     * Thus, the real URI of the ontology should be provided using the wsc-tranformer.properties
     */
    public WSCTransformer() throws Exception {
        // NOTE: The inputs and outputs of the services should be automatically translated from instances to
        // concepts using the XML Reasoner
        PropertiesConfiguration props = new PropertiesConfiguration("wsc-transformer.properties");
        this.taxonomyFile = (String) props.getProperty("taxonomy");
        // Name of the taxonomy.xml file (it will be localized automatically)
        log.info("Taxonomy file name {}", this.taxonomyFile);
        // Name of the ontology.owl file (it will be localized automatically)
        this.ontologyFile = (String) props.getProperty("ontology");
        log.info("Ontology file name {}", this.ontologyFile);
    }

    private MessageContent generateMessageContent(ArrayList<XMLInstance> instances, String fieldName,
            URL ontologyOwlUrl, InstanceResolver resolver) throws URISyntaxException {
        URI uri = URI.create(this.fakeURL + "#MessageContent_" + fieldName);
        MessageContent msg = new MessageContent(uri);
        for (XMLInstance instance : instances) {
            String concept = resolver.resolveToConcept(instance.getName());
            URI partURI = URI.create(this.fakeURL + "#MessagePart_" + concept);
            MessagePart part = new MessagePart(partURI);
            part.addModelReference(new Resource(new URI(ontologyOwlUrl.toString() + "#" + concept)));
            msg.addMandatoryPart(part);
        }
        return msg;
    }

    /*
    private MessageContent generateMessageContent(ArrayList<XMLInstance> instances, String fieldName, URL ontologyOwlUrl, WSCXMLSemanticReasoner reasoner) throws URISyntaxException {
    URI uri = URI.create(this.fakeURL + "#MessageContent_" + fieldName);
    MessageContent msg = new MessageContent(uri);
    for (XMLInstance instance : instances) {
        String concept = reasoner.getConceptInstance(instance.getName());
        URI partURI = URI.create(this.fakeURL + "#MessagePart_" + concept);
        MessagePart part = new MessagePart(partURI);
        part.addModelReference(new Resource(new URI(ontologyOwlUrl.toString() + "#" + concept)));
        msg.addMandatoryPart(part);
    }
    return msg;
    }*/

    /**
     * Transforms a datasets, defined by the XML description file of the services,
     * the taxonomy.xml file to translate instances to concepts, and the URL pointing
     * to the ontology that will be used when adding the model reference to the inputs/outputs
     * @param servicesXml
     * @param taxonomyXml
     * @param
     * @return
     */

    public List<Service> transform(InputStream servicesXml, InputStream taxonomyXml, InputStream ontologyOwlStream)
            throws ParserConfigurationException, SAXException, XPathExpressionException, IOException,
            URISyntaxException {
        // Create the reasoner
        WSCXMLSemanticReasoner reasoner = new WSCXMLSemanticReasoner(taxonomyXml);
        // Obtain the base:xml uri associated to the ontology
        URL ontologyBaseUri = obtainXmlBaseUri(ontologyOwlStream);
        return transform(servicesXml, ontologyBaseUri, reasoner);
    }

    public List<Service> transform(InputStream originalDescription, URL modelReferenceOntoUrl,
            InstanceResolver resolver) throws URISyntaxException {
        // De-serialize from XML
        XMLServices services = JAXB.unmarshal(originalDescription, XMLServices.class);
        List<Service> listServices = new ArrayList<Service>(services.getServices().size());

        // Create service models
        for (XMLService service : services.getServices()) {
            URI srvURI = URI.create(fakeURL + "#" + service.getName());
            URI opURI = URI.create(fakeURL + "/" + service.getName() + "#Operation");
            log.debug("Transforming service (Fake OWL URI: {})", srvURI);
            Service modelService = new Service(srvURI);

            // Create only one hasInput and hasOutput and mandatory parts for each input/output
            Operation operation = new Operation(opURI);

            // The modelReferenceOntoUrl must point to a valid url where the original ontology is
            operation.addInput(generateMessageContent(service.getInputs().getInstances(), "input",
                    modelReferenceOntoUrl, resolver));
            operation.addOutput(generateMessageContent(service.getOutputs().getInstances(), "output",
                    modelReferenceOntoUrl, resolver));
            operation.setLabel(service.getName() + "_op");

            modelService.addOperation(operation);
            modelService.setLabel(service.getName());
            listServices.add(modelService);
        }
        return listServices;
    }

    private List<Service> transform(InputStream originalDescription, URL modelReferenceOntoUrl,
            final WSCXMLSemanticReasoner reasoner) throws URISyntaxException {
        // De-serialize from XML
        InstanceResolver resolver = new InstanceResolver() {
            @Override
            public String resolveToConcept(String instance) {
                return reasoner.getConceptInstance(instance);
            }
        };
        return transform(originalDescription, modelReferenceOntoUrl, resolver);
    }

    /**
     * Interface method for transforming services defined in the WSC XML format. Note that, given the service
     * definition of the WSC does not have valid urls pointing to the ontology, and since they use instances
     * instead of concepts for the inputs and outputs, a single stream with the service definition is not enough.
     * Two more files are required: a taxonomy.xml to easily translate instances to concepts, and a valid taxonomy.owl
     * ontology, which is a translation of the taxonomy.xml into owl to import into iServe. The baseUri is used to
     * automatically locate these files without specifying anything more to the transformer. By default, if the
     * baseUri is http://localhost/, this method will try to open http://localhost/taxonomy.xml and will use
     * http://localhost/taxonomy.owl as the model reference URL.
     *
     * @param originalDescription The semantic Web service description(s) stream
     * @param baseUri             The base URI to use while transforming the service description. The baseUri should point to
     *                            a valid location where the baseUri/taxonomy.xml and baseUri/taxonomy.owl can be located.
     * @return
     */
    @Override
    public List<Service> transform(InputStream originalDescription, String baseUri) throws TransformationException {
        // De-serialize from XML
        // Use the baseUri to locate automatically the taxonomy.xml and ontology.owl
        if (baseUri == null) {
            throw new NullPointerException(
                    "BaseUri cannot be null. Please specify a baseUri to locate" + " the WSC files");
        }
        baseUri = baseUri.endsWith("/") ? baseUri : baseUri + "/";
        // Define the URL for the taxonomy xml file
        URL taxonomyXmlUrl;
        String taxonomyUrlStr = baseUri + this.taxonomyFile;
        try {
            taxonomyXmlUrl = new URL(taxonomyUrlStr);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw new TransformationException("There was a problem using the provided base uri " + baseUri + ". "
                    + " The taxonomy.xml URL " + taxonomyUrlStr + " is malformed.");
        }
        String ontologyUrlStr = baseUri + this.ontologyFile;
        URL ontologyOwlUrl;
        try {
            ontologyOwlUrl = new URL(ontologyUrlStr);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw new TransformationException("There was a problem using the provided base uri " + baseUri + ". "
                    + " The taxonomy.owl URL " + taxonomyUrlStr + " is malformed.");
        }
        // Create a reasoner to process the taxonomy.xml
        try {
            this.reasoner = new WSCXMLSemanticReasoner(taxonomyXmlUrl.openStream());
        } catch (IOException e) {
            e.printStackTrace();
            throw new TransformationException("Taxonomy XML file could not be located at " + taxonomyXmlUrl);
        }
        // Obtain the original xml:base uri from the owl file.
        URL ontologyBaseUri = null;
        try {
            ontologyBaseUri = obtainXmlBaseUri(ontologyOwlUrl);
            if (ontologyBaseUri == null) {
                throw new NullPointerException("The ontology xml:base uri cannot be derived automatically "
                        + "from " + ontologyOwlUrl + ". Please check that the ontology has an attribute "
                        + "xml:base within the <rdf:RDF> tag");
            }
        } catch (Exception e) {
            TransformationException ex = new TransformationException(
                    "Cannot obtain the base uri for the ontology. " + e.getMessage());
            ex.initCause(e);
            throw ex;
        }

        // Transform and return the result
        try {
            return transform(originalDescription, ontologyBaseUri, reasoner);
        } catch (URISyntaxException e) {
            TransformationException ex = new TransformationException(
                    "There were some problems trying to generate modelReferences. " + e.getMessage());
            ex.initCause(e);
            throw ex;
        }

    }

    public static URL obtainXmlBaseUri(InputStream owlStream)
            throws IOException, XPathExpressionException, ParserConfigurationException, SAXException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        // Detect namespaces
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse(owlStream);
        // Obtain the document element where the xml:base is
        Element rootElement = document.getDocumentElement();
        String baseUri = rootElement.getAttribute("xml:base");
        return new URL(baseUri);
    }

    public static URL obtainXmlBaseUri(URL taxonomyOwlUrl)
            throws IOException, XPathExpressionException, ParserConfigurationException, SAXException {
        return obtainXmlBaseUri(taxonomyOwlUrl.openStream());
    }

    @Override
    public String getSupportedMediaType() {
        return mediaType;
    }

    @Override
    public List<String> getSupportedFileExtensions() {
        return Arrays.asList("xml");
    }

    @Override
    public String getVersion() {
        return "WSC Importer 0.1";
    }

    public void setReasoner(WSCXMLSemanticReasoner reasoner) {
        this.reasoner = reasoner;
    }

    public void setTaxonomyFile(String taxonomyFile) {
        this.taxonomyFile = taxonomyFile;
    }

    public void setOntologyFile(String ontologyFile) {
        this.ontologyFile = ontologyFile;
    }
}