/*
* Created 2011-07-25
*
* (c) 2011 Otávio Calaça Xavier
*
* The MIT License
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
package br.ufg.inf.sws.rest.impl;
import impl.owls.grounding.MessageMapAtomicGroundingImpl;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.concurrent.Future;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.XML;
import org.mindswap.common.CompletedFuture;
import org.mindswap.exceptions.ExecutionException;
import org.mindswap.exceptions.ServiceNotAvailableException;
import org.mindswap.owl.OWLDataValue;
import org.mindswap.owl.OWLFactory;
import org.mindswap.owl.OWLIndividual;
import org.mindswap.owl.OWLIndividualList;
import org.mindswap.owl.OWLKnowledgeBase;
import org.mindswap.owl.OWLObjectProperty;
import org.mindswap.owl.OWLValue;
import org.mindswap.owls.grounding.MessageMap;
import org.mindswap.owls.process.variable.Input;
import org.mindswap.owls.process.variable.Output;
import org.mindswap.owls.process.variable.Parameter;
import org.mindswap.query.ValueMap;
import org.mindswap.utils.Utils;
import org.mindswap.utils.XSLTEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import br.ufg.inf.rest.WADLApplication;
import br.ufg.inf.rest.WADLParameter;
import br.ufg.inf.rest.WADLRequest;
import br.ufg.inf.rest.WADLRequestImpl;
import br.ufg.inf.rest.WADLResource;
import br.ufg.inf.sws.rest.WADLAtomicGrounding;
import br.ufg.inf.sws.rest.WADLGrounding;
import br.ufg.inf.sws.rest.WADLGroundingFactory;
import br.ufg.inf.sws.rest.WADLResourceMethodRef;
import br.ufg.inf.sws.rest.vocabulary.OWLSRestful;
/**
* Default implementation of {@link WADLAtomicGrounding}.
*
* @author Otávio Calaça Xavier <otaviocx@gmail.com>
*
*/
public class WADLAtomicGroundingImpl extends MessageMapAtomicGroundingImpl<TransformationFileMap> implements WADLAtomicGrounding {
private static final Logger logger = LoggerFactory.getLogger(WADLAtomicGroundingImpl.class);
/**
* The WADLResource instance, that executes the requests for resources.
*/
private WADLResource wadlResource;
/**
* @param ind
* Entity that represents the corresponding ontological class.
*/
public WADLAtomicGroundingImpl(OWLIndividual ind) {
super(ind);
}
/* (non-Javadoc)
* @see org.mindswap.owls.grounding.AtomicGrounding#getDescriptionURL()
*/
public URL getDescriptionURL() {
try {
return getWADL().toURL();
} catch(final MalformedURLException e) {
return null;
}
}
/* (non-Javadoc)
* @see org.mindswap.owls.grounding.AtomicGrounding#invoke(org.mindswap.query.ValueMap)
*/
public Future<ValueMap<Output, OWLValue>> invoke(ValueMap<Input, OWLValue> values) {
return invoke(values, OWLFactory.createKB());
}
/* (non-Javadoc)
* @see org.mindswap.owls.grounding.AtomicGrounding#invoke(org.mindswap.query.ValueMap, org.mindswap.owl.OWLKnowledgeBase)
*/
public Future<ValueMap<Output, OWLValue>> invoke(ValueMap<Input, OWLValue> inputs, OWLKnowledgeBase env) {
try
{
initWADLResource();
for (final WADLParameter in : wadlResource.getInputs())
{
final MessageMap<TransformationFileMap> mp = getMessageMap(true, in.getId());
if (mp == null) continue;
final Input input = mp.getOWLSParameter().castTo(Input.class);
OWLValue inputValue = null;
try {
inputValue = getParameterValue(input, inputs);
} catch (ExecutionException e) {
if(in.getValue() != null) {
inputValue = env.createDataValue(in.getValue());
inputs.setValue(input, inputValue);
}
}
if(inputValue != null) {
Object inputValueObj;
TransformationFileMap transf = mp.getTransformation();
String xslt = null;
if(transf != null)
xslt = transf.getTransformationURI().toString();
if (inputValue.isIndividual())
{
final String rdfXML = ((OWLIndividual) inputValue).toRDF(true, true);
if (xslt != null)
{
final String xsltResult = XSLTEngine.transform(rdfXML, xslt, inputs);
inputValueObj = Utils.getAsNode(xsltResult);
if (inputValueObj == null) inputValueObj = xsltResult.trim();
}
else
{
logger.debug("No XSLT transformation for input parameter " + input + " specified." +
" OWLIndividual bound to this parameter should be transformed rather than using" +
" its RDF/XML serialization.");
inputValueObj = rdfXML;
}
}
else // it is a OWLDataValue
{
if (xslt != null) throw new ExecutionException("XSLT transformation for input parameter " +
input + " cannot be applied to OWL data value (only to OWL individual).");
inputValueObj = ((OWLDataValue) inputValue).getValue();
}
in.setValue(inputValueObj);
}
}
wadlResource.invoke();
final ValueMap<Output, OWLValue> results = new ValueMap<Output, OWLValue>();
for (final Output outputParam : getProcess().getOutputs())
{
final MessageMap<TransformationFileMap> mp = getMessageMap(outputParam);
final TransformationFileMap transformation = mp.getTransformation();
final String wadlMessageParam = mp.getGroundingParameter();
WADLParameter out = wadlResource.getOutput(wadlMessageParam);
//WADLParameter out = wadlResource.getRepresentation();
Object outputValue = out.getValue();
if(outputValue != null) {
if (outputParam.getParamType().isDataType()) {
results.setValue(outputParam, env.createDataValue(outputValue));
} else {
String outputString = outputValue.toString();
if(out.getMediaType().indexOf("json") > -1 || out.getMediaType().indexOf("javascript") > -1) {
Object obj = null;
try {
obj = new JSONObject(outputString);
} catch (Exception e) {
obj = new JSONArray(outputString);
}
if(obj != null)
outputString = XML.toString(obj, "json");
}
if(transformation != null && transformation.getTransformationMediaType().indexOf("xsl") > -1) {
WADLRequest req = new WADLRequestImpl();
String xslt = (String) req.request(transformation.getTransformationURI().toString(), "GET");
outputString = XSLTEngine.transform(outputString, xslt, inputs);
results.setValue(outputParam, env.parseLiteral(outputString));
} else {
results.setValue(outputParam, env.createDataValue(outputString));
}
}
}
}
return CompletedFuture.createSuccessCompletionFuture(results);
}
catch(final Exception e)
{
return CompletedFuture.createExceptionCompletionFuture(e);
}
}
/* (non-Javadoc)
* @see org.mindswap.owls.grounding.AtomicGrounding#getGrounding()
*/
public WADLGrounding getGrounding() {
return getGrounding(WADLGrounding.class);
}
/* (non-Javadoc)
* @see org.mindswap.owls.grounding.AtomicGrounding#getGroundingType()
*/
public String getGroundingType() { return WADLAtomicGrounding.GROUNDING_WADL; }
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#setWADL(java.net.URI)
*/
public void setWADL(URI wadlLoc) {
setProperty(OWLSRestful.wadlDocument, wadlLoc);
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#getWADL()
*/
public URI getWADL() {
return getPropertyAsURI(OWLSRestful.wadlDocument);
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#setMethod(java.net.URI)
*/
public void setMethod(URI method) {
WADLResourceMethodRef rmRef = getResourceMethodRef();
if (rmRef == null)
{
//TODO Create method createWADLResourceMethodRef in OWLModel
rmRef = WADLGroundingFactory.createWADLResourceMethodRef(null, getOntology());
setResourceMethodRef(rmRef);
}
rmRef.setMethod(method);
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#getMethod()
*/
public URI getMethod() {
return getResourceMethodRef().getMethod();
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#setResource(java.net.URI)
*/
public void setResource(URI resource) {
WADLResourceMethodRef rmRef = getResourceMethodRef();
if (rmRef == null)
{
//TODO Create method createWADLResourceMethodRef in OWLModel
rmRef = WADLGroundingFactory.createWADLResourceMethodRef(null, getOntology());
setResourceMethodRef(rmRef);
}
rmRef.setResource(resource);
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#getResource()
*/
public URI getResource() {
return getResourceMethodRef().getResource();
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#setResourceMethodRef(br.ufg.inf.sws.rest.WADLResourceMethodRef)
*/
public void setResourceMethodRef(WADLResourceMethodRef rmRef) {
setProperty(OWLSRestful.wadlResourceMethod, rmRef);
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#getResourceMethodRef()
*/
public WADLResourceMethodRef getResourceMethodRef() {
return getPropertyAs(OWLSRestful.wadlResourceMethod, WADLResourceMethodRef.class);
}
/* (non-Javadoc)
* @see impl.owls.grounding.MessageMapAtomicGroundingImpl#createInputMessageMap()
*/
protected MessageMap<TransformationFileMap> createInputMessageMap() {
//TODO Create method createWADLRequestParamMap in OWLModel
return WADLGroundingFactory.createWADLRequestParamMap(null, getOntology());
}
/* (non-Javadoc)
* @see impl.owls.grounding.MessageMapAtomicGroundingImpl#createOutputMessageMap()
*/
protected MessageMap<TransformationFileMap> createOutputMessageMap() {
//TODO Create method createWADLResponseParamMap in OWLModel
return WADLGroundingFactory.createWADLResponseParamMap(null, getOntology());
}
/* (non-Javadoc)
* @see impl.owls.grounding.MessageMapAtomicGroundingImpl#inputMessageMapProperty()
*/
protected OWLObjectProperty inputMessageMapProperty() {
return OWLSRestful.wadlRequestParam;
}
/* (non-Javadoc)
* @see impl.owls.grounding.MessageMapAtomicGroundingImpl#outputMessageMapProperty()
*/
protected OWLObjectProperty outputMessageMapProperty() {
return OWLSRestful.wadlResponseParam;
}
/* (non-Javadoc)
* @see impl.owls.grounding.MessageMapAtomicGroundingImpl#messageMapType()
*/
protected Class<? extends MessageMap<TransformationFileMap>> messageMapType() {
return WADLMessageParamMap.class;
}
/* (non-Javadoc)
* @see br.ufg.inf.sws.rest.WADLAtomicGrounding#getWADLParameter(org.mindswap.owls.process.variable.Parameter)
*/
public URI getWADLParameter(final Parameter parameter) {
URI uri = getWADLParameter(parameter, getInputMappings());
if (uri == null) uri = getWADLParameter(parameter, getOutputMappings());
return uri;
}
/**
* Method that search for a parameter in a list and returns its URI.
* @param parameter
* A parameter that which the URI is wanted.
* @param list
* A list of parameters.
* @return The URI of the given parameter.
*/
private URI getWADLParameter(final Parameter parameter,
final OWLIndividualList<? extends MessageMap<TransformationFileMap>> list) {
for (final MessageMap<TransformationFileMap> messageMap : list) {
if (messageMap.getOWLSParameter().equals(parameter))
return messageMap.getGroundingParameterAsURI();
}
return null;
}
/**
* Method that removes the WADLResourceMethodRef reference of the property wadlResourceMethod
*/
public void removeResourceMethodRef() {
if (hasProperty(OWLSRestful.wadlResourceMethod)) {
final WADLResourceMethodRef rmRef = getResourceMethodRef();
rmRef.removeResource();
rmRef.removeMethod();
removeProperty(OWLSRestful.wadlResourceMethod, null);
rmRef.delete();
}
}
/**
* Method that removes all setted properties of the ontological class.
*/
private void removeAll() {
removeProperty(OWLSRestful.wadlDocument, null);
removeResourceMethodRef();
removeProperty(OWLSRestful.wadlRequestParam, null);
removeProperty(OWLSRestful.wadlResponseParam, null);
removeMessageMaps(true);
removeMessageMaps(false);
}
/* (non-Javadoc)
* @see impl.owl.WrappedIndividual#delete()
*/
public void delete() {
removeAll();
super.delete();
}
/**
* Method that initialize the WADLResource instance with the informations of resource and method.
* @throws ExecutionException When the resource not found in the WADL description.
*/
private void initWADLResource() throws ExecutionException
{
if (wadlResource == null)
{
final String resource = getResource().toString();
final String method = getMethod().toString();
final WADLApplication a;
try
{
a = WADLApplication.createApplication(getWADL());
}
catch (final Exception e)
{
throw new ServiceNotAvailableException(getProcess(), e);
}
wadlResource = a.getResource(resource, method);
if (wadlResource == null)
throw new ExecutionException("Resource " + resource + " not found in the WADL description");
}
}
}