/* * Copyright (c) 2013-2015 Josef Hardi <josef.hardi@gmail.com> * * 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 com.obidea.semantika.queryanswer.processor; import java.util.ArrayList; import java.util.List; import com.obidea.semantika.database.sql.base.ISqlExpression; import com.obidea.semantika.exception.SemantikaRuntimeException; import com.obidea.semantika.expression.base.ExpressionConstant; import com.obidea.semantika.expression.base.IFunction; import com.obidea.semantika.expression.base.ILiteral; import com.obidea.semantika.expression.base.ITerm; import com.obidea.semantika.expression.base.IUriReference; import com.obidea.semantika.expression.base.IVariable; import com.obidea.semantika.expression.base.TermVisitorAdapter; import com.obidea.semantika.knowledgebase.TermSubstitutionBinding; import com.obidea.semantika.knowledgebase.UnificationException; import com.obidea.semantika.knowledgebase.Unifier; import com.obidea.semantika.mapping.IUriTemplate; import com.obidea.semantika.mapping.base.sql.SqlAddition; import com.obidea.semantika.mapping.base.sql.SqlAnd; import com.obidea.semantika.mapping.base.sql.SqlColumn; import com.obidea.semantika.mapping.base.sql.SqlDivide; import com.obidea.semantika.mapping.base.sql.SqlEqualsTo; import com.obidea.semantika.mapping.base.sql.SqlFunction; import com.obidea.semantika.mapping.base.sql.SqlGreaterThan; import com.obidea.semantika.mapping.base.sql.SqlGreaterThanEquals; import com.obidea.semantika.mapping.base.sql.SqlIsNotNull; import com.obidea.semantika.mapping.base.sql.SqlIsNull; import com.obidea.semantika.mapping.base.sql.SqlLessThan; import com.obidea.semantika.mapping.base.sql.SqlLessThanEquals; import com.obidea.semantika.mapping.base.sql.SqlMappingFactory; import com.obidea.semantika.mapping.base.sql.SqlMultiply; import com.obidea.semantika.mapping.base.sql.SqlNotEqualsTo; import com.obidea.semantika.mapping.base.sql.SqlOr; import com.obidea.semantika.mapping.base.sql.SqlSubtract; import com.obidea.semantika.mapping.base.sql.SqlUriConcat; import com.obidea.semantika.mapping.base.sql.SqlUriValue; import com.obidea.semantika.mapping.base.sql.SqlValue; import com.obidea.semantika.util.Serializer; public class TermToSqlConverter extends TermVisitorAdapter // XXX: Fix this, maybe SqlMappingVisitorAdapter { private ISqlExpression mReturnExpression = null; private static SqlMappingFactory sSqlFactory = SqlMappingFactory.getInstance(); private void reset() { mReturnExpression = null; } public ISqlExpression toSqlExpression(ITerm term) { reset(); term.accept(this); if (mReturnExpression == null) { throw new SemantikaRuntimeException("Unable to convert term (class: " + term.getClass().toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } return mReturnExpression; } public SqlValue toSqlValue(ILiteral literal) { return sSqlFactory.createValueExpression(literal.getLexicalValue(), literal.getDatatype()); } public SqlUriValue toSqlUriValue(IUriReference uriReference) { return sSqlFactory.createUriValueExpression(uriReference.toUri()); } public SqlAnd toSqlAnd(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createAndExpression(e1, e2); } public SqlOr toSqlOr(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createOrExpression(e1, e2); } public SqlEqualsTo toSqlEqualsTo(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createEqualsToExpression(e1, e2); } public SqlNotEqualsTo toSqlNotEqualsTo(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createNotEqualsToExpression(e1, e2); } public SqlGreaterThan toSqlGreaterThan(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createGreaterThanExpression(e1, e2); } public SqlGreaterThanEquals toSqlGreaterThanEqual(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createGreaterThanEqualsExpression(e1, e2); } public SqlLessThan toSqlLessThan(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createLessThanExpression(e1, e2); } public SqlLessThanEquals toSqlLessThanEqual(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createLessThanEqualsExpression(e1, e2); } public SqlAddition toSqlAddition(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createAdditionExpression(e1, e2); } public SqlSubtract toSqlSubtract(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createSubstractExpression(e1, e2); } public SqlMultiply toSqlMultiply(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createMultiplyExpression(e1, e2); } public SqlDivide toSqlDivide(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); return sSqlFactory.createDivideExpression(e1, e2); } public SqlIsNull toSqlIsNull(IFunction function) { ISqlExpression e = getExpression(function.getParameter(0)); return sSqlFactory.createIsNullExpression(e); } public SqlIsNotNull toSqlIsNotNull(IFunction function) { ISqlExpression e = getExpression(function.getParameter(0)); return sSqlFactory.createIsNotNullExpression(e); } public SqlUriConcat toSqlUriConcat(IUriTemplate uriTemplate) { String templateString = uriTemplate.getTemplateString(); SqlValue templateValue = sSqlFactory.createStringValueExpression(templateString); List<ISqlExpression> parameters = new ArrayList<ISqlExpression>(); parameters.add(templateValue); for (ITerm templateParameter : uriTemplate.getParameters()) { parameters.add(getExpression(templateParameter)); } return sSqlFactory.createUriConcatExpression(parameters); } private ISqlExpression toSqlRegex(IFunction function) { ISqlExpression e1 = getExpression(function.getParameter(0)); ISqlExpression e2 = getExpression(function.getParameter(1)); ISqlExpression e3 = getExpression(function.getParameter(2)); return sSqlFactory.createRegexExpression(e1, e2, e3); } private ISqlExpression toSqlLang(IFunction function) { ISqlExpression e = getExpression(function.getParameter(0)); return sSqlFactory.createLangExpression(e); } private ISqlExpression toSqlStr(IFunction function) { ISqlExpression e = getExpression(function.getParameter(0)); return sSqlFactory.createStrExpression(e); } /* * Implementation of visitor methods. */ @Override public void visit(IVariable variable) { mReturnExpression = (variable instanceof SqlColumn) ? (SqlColumn) variable : null; } @Override public void visit(ILiteral literal) { mReturnExpression = (literal instanceof SqlValue) ? (SqlValue) literal : toSqlValue(literal); } @Override public void visit(IUriReference uriReference) { mReturnExpression = toSqlUriValue(uriReference); } @Override public void visit(IFunction function) { mReturnExpression = (function instanceof SqlFunction) ? (SqlFunction) function : visitFunction(function); } private ISqlExpression visitFunction(IFunction function) { return (function instanceof IUriTemplate) ? visitUriTemplateFunction((IUriTemplate) function) : visitBuildInFunction(function); } private ISqlExpression visitUriTemplateFunction(IUriTemplate uriTemplate) { return toSqlUriConcat(uriTemplate); } private ISqlExpression visitBuildInFunction(IFunction function) { String functionName = function.getName(); if (functionName.equals(ExpressionConstant.AND)) { return toSqlAnd(function); } else if (functionName.equals(ExpressionConstant.OR)) { return toSqlOr(function); } else if (functionName.equals(ExpressionConstant.EQUAL)) { ITerm t1 = function.getParameter(0); ITerm t2 = function.getParameter(1); if (t1 instanceof IUriTemplate && t2 instanceof IUriReference) { mReturnExpression = getExtendedEqualExpression(t1, t2); } else if (t2 instanceof IUriTemplate && t1 instanceof IUriReference) { mReturnExpression = getExtendedEqualExpression(t2, t1); } else if (t1 instanceof IUriTemplate && t2 instanceof IUriTemplate) { mReturnExpression = getExtendedEqualExpression(t2, t1); } else { return toSqlEqualsTo(function); } } else if (functionName.equals(ExpressionConstant.NOT_EQUAL)) { ITerm t1 = function.getParameter(0); ITerm t2 = function.getParameter(1); if (t1 instanceof IUriTemplate && t2 instanceof IUriReference) { mReturnExpression = getExtendedNotEqualExpression(t1, t2); } else if (t2 instanceof IUriTemplate && t1 instanceof IUriReference) { mReturnExpression = getExtendedNotEqualExpression(t1, t2); } else if (t1 instanceof IUriTemplate && t2 instanceof IUriTemplate) { mReturnExpression = getExtendedNotEqualExpression(t1, t2); } else { mReturnExpression = toSqlNotEqualsTo(function); } } else if (functionName.equals(ExpressionConstant.GREATER_THAN)) { mReturnExpression = toSqlGreaterThan(function); } else if (functionName.equals(ExpressionConstant.GREATER_THAN_EQUAL)) { mReturnExpression = toSqlGreaterThanEqual(function); } else if (functionName.equals(ExpressionConstant.LESS_THAN)) { mReturnExpression = toSqlLessThan(function); } else if (functionName.equals(ExpressionConstant.LESS_THEN_EQUAL)) { mReturnExpression = toSqlLessThanEqual(function); } else if (functionName.equals(ExpressionConstant.ADD)) { mReturnExpression = toSqlAddition(function); } else if (functionName.equals(ExpressionConstant.SUBTRACT)) { mReturnExpression = toSqlSubtract(function); } else if (functionName.equals(ExpressionConstant.MULTIPLY)) { mReturnExpression = toSqlMultiply(function); } else if (functionName.equals(ExpressionConstant.DIVIDE)) { mReturnExpression = toSqlDivide(function); } else if (functionName.equals(ExpressionConstant.IS_NULL)) { mReturnExpression = toSqlIsNull(function); } else if (functionName.equals(ExpressionConstant.IS_NOT_NULL)) { mReturnExpression = toSqlIsNotNull(function); } else if (functionName.equals(ExpressionConstant.REGEX)) { mReturnExpression = toSqlRegex(function); } else if (functionName.equals(ExpressionConstant.LANG)) { mReturnExpression = toSqlLang(function); } else if (functionName.equals(ExpressionConstant.STR)) { mReturnExpression = toSqlStr(function); } else { throw new SemantikaRuntimeException("Unknown function name: " + functionName); //$NON-NLS-1$ } return mReturnExpression; } /* * Other private utility methods */ private ISqlExpression getExtendedEqualExpression(ITerm t1, ITerm t2) { ISqlExpression toReturn = null; try { TermSubstitutionBinding binding = Unifier.findSubstitution(t1, t2); for (IVariable variable : binding.getVariables()) { ISqlExpression e1 = getExpression(variable); ISqlExpression e2 = getExpression(binding.getTerm(variable)); if (toReturn == null) { toReturn = sSqlFactory.createEqualsToExpression(e1, e2); } else { toReturn = sSqlFactory.createAndExpression(toReturn, sSqlFactory.createEqualsToExpression(e1, e2)); } } return toReturn; } catch (UnificationException e) { throw new SemantikaRuntimeException("Unexpected exception when processing UriTemplate filters", e); //$NON-NLS-1$ } } private ISqlExpression getExtendedNotEqualExpression(ITerm t1, ITerm t2) { ISqlExpression toReturn = null; try { TermSubstitutionBinding binding = Unifier.findSubstitution(t1, t2); for (IVariable variable : binding.getVariables()) { ISqlExpression e1 = getExpression(variable); ISqlExpression e2 = getExpression(binding.getTerm(variable)); if (toReturn == null) { toReturn = sSqlFactory.createNotEqualsToExpression(e1, e2); } else { toReturn = sSqlFactory.createAndExpression(toReturn, sSqlFactory.createNotEqualsToExpression(e1, e2)); } } return toReturn; } catch (UnificationException e) { throw new SemantikaRuntimeException("Unexpected exception when processing UriTemplate filters", e); //$NON-NLS-1$ } } private ISqlExpression getExpression(ITerm term) { term.accept(this); return copy(mReturnExpression); } private static ISqlExpression copy(ISqlExpression expression) { return (ISqlExpression) Serializer.copy(expression); } }