package org.aksw.sparqlify.core.rewrite.expr.transform; import org.aksw.jena_sparql_api.views.E_RdfTerm; import org.aksw.jena_sparql_api.views.ExprCopy; import org.aksw.jena_sparql_api.views.SparqlifyConstants; import org.aksw.jena_sparql_api.views.SqlTranslationUtils; import org.apache.jena.rdf.model.Resource; import org.apache.jena.sparql.expr.E_Conditional; import org.apache.jena.sparql.expr.E_Equals; import org.apache.jena.sparql.expr.E_LogicalAnd; import org.apache.jena.sparql.expr.E_LogicalOr; import org.apache.jena.sparql.expr.Expr; import org.apache.jena.sparql.expr.ExprFunction; import org.apache.jena.sparql.expr.NodeValue; /** * * * * * @author Claus Stadler <cstadler@informatik.uni-leipzig.de> * */ public class ExprTransformerArithmetic extends ExprTransformerBase2 { private Resource resultType; public ExprTransformerArithmetic(Resource resultType) { this.resultType = resultType; } public Expr handleConcat(ExprFunction fn) { // The result is null if it could not be further transformed Expr result = SqlTranslationUtils.optimizeOpConcat(fn); /* if(result == null) { result = fn; }*/ return result; } @Override public E_RdfTerm transform(Expr orig, E_RdfTerm a, E_RdfTerm b) { // Create an expression base on the arguments // using the type of the original expression Expr isCompatibleTypes = ExprTransformerRdfTermComparator.createTypeCheck(a, b); E_RdfTerm result; if(isCompatibleTypes.equals(SparqlifyConstants.nvTypeError)) { result = SqlTranslationUtils.expandConstant(SparqlifyConstants.nvTypeError); } else { Expr va = a.getLexicalValue(); Expr vb = b.getLexicalValue(); Expr ex = ExprCopy.getInstance().copy(orig, va, vb); if(isCompatibleTypes.equals(NodeValue.TRUE)) { result = E_RdfTerm.createTypedLiteral(ex, resultType); } else { Expr cond = new E_Conditional(isCompatibleTypes, ex, SparqlifyConstants.nvTypeError); result = E_RdfTerm.createTypedLiteral(cond, resultType); } } return result; } public static final NodeValue two = NodeValue.makeDecimal(2); public static final NodeValue three = NodeValue.makeDecimal(3); public static Expr createTypeCheck(E_RdfTerm a, E_RdfTerm b) { // Condition: Either the types are equal or both are either 2 (plain) or 3 (typed literal) // TODO Already evaluate here as far as possible - Otherwise the expressions get annoyingly complicated Expr at = a.getType(); Expr bt = b.getType(); Expr result; if(at.isConstant() && bt.isConstant()) { NodeValue x = at.getConstant(); NodeValue y = at.getConstant(); boolean isSameValue = NodeValue.sameAs(x, y); boolean isBothLiterals = (NodeValue.sameAs(x, two) || NodeValue.sameAs(x, three)) && (NodeValue.sameAs(y, two) || NodeValue.sameAs(y, three)); boolean isCompatibleTypes = isSameValue || isBothLiterals; if(isCompatibleTypes) { result = NodeValue.TRUE; } else { result = SparqlifyConstants.nvTypeError; } } else { Expr eqTmpA = new E_Equals(a.getType(), b.getType()); Expr e = new E_LogicalAnd( new E_LogicalOr( new E_Equals(a.getType(), NodeValue.makeDecimal(2)), new E_Equals(a.getType(), NodeValue.makeDecimal(3)) ), new E_LogicalOr( new E_Equals(b.getType(), NodeValue.makeDecimal(2)), new E_Equals(b.getType(), NodeValue.makeDecimal(3)) ) ); Expr eqTA = new E_LogicalOr(eqTmpA, e); result = new E_Conditional(eqTA, NodeValue.TRUE, SparqlifyConstants.nvTypeError); } return result; } public static E_RdfTerm processOpRdfTerm(E_RdfTerm a, E_RdfTerm b, Expr innerExpr, Resource resultType) { // Condition: Either the types are equal or both are either 2 (plain) or 3 (typed literal) Expr eqT = createTypeCheck(a, b); //Expr eqV = new E_Equals(a.getLexicalValue(), b.getLexicalValue()); Expr eqV = innerExpr; // TODO We need to consider type hierarchies, but for now we just skip on that. Expr eqD = NodeValue.TRUE; //Expr eqD = new E_Equals(a.getDatatype(), b.getDatatype()); Expr eqL = new E_Equals(a.getLanguageTag(), b.getLanguageTag()); Expr tmp = new E_LogicalAnd( new E_LogicalAnd(eqT, eqV), new E_LogicalAnd(eqD, eqL) ); E_RdfTerm result = E_RdfTerm.createTypedLiteral(tmp, resultType); return result; } }