package org.aksw.sparqlify.core.rewrite.expr.transform; import java.util.ArrayList; import java.util.List; import org.aksw.jena_sparql_api.utils.ExprUtils; import org.aksw.jena_sparql_api.views.E_RdfTerm; import org.aksw.jena_sparql_api.views.SparqlifyConstants; import org.aksw.sparqlify.type_system.CandidateMethod; import org.aksw.sparqlify.type_system.FunctionModel; import org.aksw.sparqlify.type_system.MethodDeclaration; import org.aksw.sparqlify.type_system.TypeSystemUtils; import org.apache.jena.sparql.expr.E_Function; import org.apache.jena.sparql.expr.Expr; import org.apache.jena.sparql.expr.ExprFunction; import org.apache.jena.sparql.expr.ExprList; import org.apache.jena.sparql.expr.NodeValue; import org.apache.jena.vocabulary.XSD; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ExprTransformerSparqlFunctionModel implements ExprTransformer { private static final Logger logger = LoggerFactory.getLogger(ExprTransformerSparqlFunctionModel.class); // TODO Move to appropriate place private static E_RdfTerm typeError = E_RdfTerm.createTypedLiteral(SparqlifyConstants.nvTypeError, SparqlifyConstants.nvTypeError); private FunctionModel<String> sparqlModel; public ExprTransformerSparqlFunctionModel(FunctionModel<String> sparqlModel) { this.sparqlModel = sparqlModel; } public static List<Expr> getTermValues(List<E_RdfTerm> rdfTerms) { List<Expr> result = new ArrayList<Expr>(rdfTerms.size()); for(E_RdfTerm rdfTerm : rdfTerms) { Expr item = rdfTerm.getLexicalValue(); result.add(item); } return result; } @Override public E_RdfTerm transform(Expr orig, List<E_RdfTerm> exprs) { ExprFunction fn = orig.getFunction(); String fnName = ExprUtils.getFunctionId(fn); // Get the argument type list // All of the arguments must be typed literals (maybe also plain literal???) // otherwise its an type error List<String> argTypes = new ArrayList<String>(exprs.size()); for(E_RdfTerm rdfTerm : exprs) { Expr termType = rdfTerm.getType(); Expr datatype = rdfTerm.getDatatype(); if(!termType.isConstant()) { logger.debug("Yielding type error because termType is not a contant in: " + rdfTerm + " from " + orig + " with " + exprs); return typeError; } int termTypeVal = termType.getConstant().getDecimal().intValue(); if(!datatype.isConstant()) { logger.debug("Yielding type error because datatype is not a contant in: " + rdfTerm + " from " + orig + " with " + exprs); return typeError; } NodeValue nodeValue = datatype.getConstant(); if(nodeValue.equals(SparqlifyConstants.nvTypeError)) { //SqlValue.TYPE_ERROR)) { logger.debug("Passing on type error for: " + fnName + " " + exprs); return typeError; } if(!nodeValue.isString()) { logger.debug("Yielding type error because datatype is not a string for: " + fnName + " " + exprs); return typeError; } String datatypeStr = nodeValue.asUnquotedString(); // Convert a plain literal to a typed literal with xsd:string if(termTypeVal == 2) { if(!datatypeStr.trim().isEmpty()) { logger.debug("Yielding type error because termType has a language tag in : " + rdfTerm + " from " + orig + " with " + exprs); return typeError; } datatypeStr = XSD.xstring.toString(); } else { if(termTypeVal != 3) { logger.debug("Yielding type error because termType is not 3 (typed literal) in: " + rdfTerm + " from " + orig + " with " + exprs); return typeError; } } argTypes.add(datatypeStr); } //FunctionModel CandidateMethod<String> candidate = TypeSystemUtils.lookupCandidate(sparqlModel, fnName, argTypes); E_RdfTerm result; if(candidate == null) { logger.debug("Yielding type error because no suitable candidate found for " + fnName + " with " + argTypes); return typeError; } MethodDeclaration<String> dec = candidate.getMethod().getDeclaration(); String name = dec.getName(); String returnType = dec.getSignature().getReturnType(); NodeValue nvReturnType = NodeValue.makeString(returnType); ExprList newArgs = new ExprList(getTermValues(exprs)); ExprFunction exprFn = new E_Function(name, newArgs); result = E_RdfTerm.createTypedLiteral(exprFn, nvReturnType); return result; } }