[Mulgara-svn] r822 - branches/mgr-61-sparql/src/jar/sparql-interpreter/java/org/mulgara/sparql
pag at mulgara.org
pag at mulgara.org
Wed Apr 23 06:41:18 UTC 2008
Author: pag
Date: 2008-04-22 23:41:17 -0700 (Tue, 22 Apr 2008)
New Revision: 822
Added:
branches/mgr-61-sparql/src/jar/sparql-interpreter/java/org/mulgara/sparql/FilterMapper.java
Log:
Set up the framework for mapping CST Expressions from the SPARQL project into Mulgara AST elements in the org.mulgara.query.filter package. Got about half of the expressions mapped at the moment.
Added: branches/mgr-61-sparql/src/jar/sparql-interpreter/java/org/mulgara/sparql/FilterMapper.java
===================================================================
--- branches/mgr-61-sparql/src/jar/sparql-interpreter/java/org/mulgara/sparql/FilterMapper.java (rev 0)
+++ branches/mgr-61-sparql/src/jar/sparql-interpreter/java/org/mulgara/sparql/FilterMapper.java 2008-04-23 06:41:17 UTC (rev 822)
@@ -0,0 +1,266 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.sparql;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.mulgara.sparql.parser.cst.BooleanLiteral;
+import org.mulgara.sparql.parser.cst.DecimalLiteral;
+import org.mulgara.sparql.parser.cst.DoubleLiteral;
+import org.mulgara.sparql.parser.cst.Expression;
+import org.mulgara.sparql.parser.cst.FunctionCall;
+import org.mulgara.sparql.parser.cst.IRIReference;
+import org.mulgara.sparql.parser.cst.IntegerLiteral;
+import org.mulgara.sparql.parser.cst.Divide;
+import org.mulgara.sparql.parser.cst.Minus;
+import org.mulgara.sparql.parser.cst.Multiply;
+import org.mulgara.sparql.parser.cst.Plus;
+import org.mulgara.sparql.parser.cst.RDFLiteral;
+import org.mulgara.sparql.parser.cst.UnaryMinus;
+import org.mulgara.sparql.parser.cst.UnaryPlus;
+import org.mulgara.sparql.parser.cst.Variable;
+import org.mulgara.parser.MulgaraParserException;
+import org.mulgara.query.filter.Filter;
+import org.mulgara.query.filter.RDFTerm;
+import org.mulgara.query.filter.arithmetic.AddOperation;
+import org.mulgara.query.filter.arithmetic.DivideOperation;
+import org.mulgara.query.filter.arithmetic.MinusOperation;
+import org.mulgara.query.filter.arithmetic.MultiplyOperation;
+import org.mulgara.query.filter.value.Bool;
+import org.mulgara.query.filter.value.ExternalFn;
+import org.mulgara.query.filter.value.IRI;
+import org.mulgara.query.filter.value.NumericExpression;
+import org.mulgara.query.filter.value.NumericLiteral;
+import org.mulgara.query.filter.value.SimpleLiteral;
+import org.mulgara.query.filter.value.TypedLiteral;
+import org.mulgara.query.filter.value.Var;
+
+
+/**
+ * This object maps a constraint from an {@link org.mulgara.sparql.parser.cst.Expression} into a
+ * {@link org.mulgara.query.filter.Filter}.
+ *
+ * @created Apr 22, 2008
+ * @author Paul Gearon
+ * @copyright © 2008 <a href="http://www.topazproject.org/">The Topaz Project</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class FilterMapper {
+
+ /** Represents the CST Filter expression that is to be mapped. */
+ private Expression cstFilter;
+
+ public FilterMapper(Expression cstFilter) {
+ this.cstFilter = cstFilter;
+ }
+
+ /**
+ * Get the Filter object described by the expression.
+ * @return A new Filter for use in a query.
+ * @throws MulgaraParserException If the mapping could not be performed due to structural errors in the CST.
+ */
+ public Filter getFilter() throws MulgaraParserException {
+ RDFTerm term = mapExpression(cstFilter);
+ if (!(term instanceof Filter)) throw new MulgaraParserException("Bad structure in the FILTER");
+ return (Filter)term;
+ }
+
+ /**
+ * The internal method for mapping a CST expression into an AST term.
+ * @param expr The expression to be mapped.
+ * @return A new AST term.
+ * @throws MulgaraParserException If the mapping could not be performed due to structural errors in the CST.
+ */
+ private RDFTerm mapExpression(Expression expr) throws MulgaraParserException {
+ ExpressionToTerm<? extends Expression> mapper = mappers.get(expr.getClass());
+ if (mapper == null) throw new UnsupportedOperationException("Unable to handle expression: \"" + expr.getImage() + "\" (" + expr.getClass().getSimpleName() + ")");
+ return mapper.map(expr, this);
+ }
+
+ /**
+ * Converts a list of CST NumericExpressions into a list of AST NumericExpressions.
+ * @param operands The list of CST numeric expressions.
+ * @return A list of AST numeric expressions.
+ * @throws MulgaraParserException If one of the values was not mapped to an AST numeric expression.
+ */
+ private List<NumericExpression> mapNumbers(List<org.mulgara.sparql.parser.cst.NumericExpression> operands) throws MulgaraParserException {
+ List<NumericExpression> numbers = new ArrayList<NumericExpression>(operands.size());
+ for (org.mulgara.sparql.parser.cst.NumericExpression e: operands) {
+ RDFTerm op = mapExpression(e);
+ if (!(op instanceof NumericExpression)) throw new MulgaraParserException("Non-numeric value in arithmetic operation: " + op.getClass().getSimpleName());
+ numbers.add((NumericExpression)op);
+ }
+ return numbers;
+ }
+
+ /** Defines an interface for mapping expressions into an equivalent Filter operation. */
+ private static interface ExpressionToTerm<T extends Expression> {
+ /**
+ * A main entry point for the mapper, which will do the casting into {@link #typedMap(Expression, FilterMapper)}.
+ * @param expr The expression to map to an RDFTerm.
+ * @param parent The surrounding FilterMapper class.
+ * @return A {@link RDFTerm} that is the equivalent to the given expression.
+ */
+ public RDFTerm map(Expression expr, FilterMapper parent) throws MulgaraParserException;
+ /**
+ * Convert an Expression to a RDFTerm for Mulgara.
+ * @param expr The Expression to convert. Should be specific to the mapper.
+ * @return The RDFTerm relevant to the mapper.
+ */
+ RDFTerm typedMap(T pattern, FilterMapper parent) throws MulgaraParserException;
+ /** Identify the class to be mapped by the extension. */
+ public Class<T> getMapType();
+ }
+
+ private static abstract class AbstractExprToFilter<T extends Expression> implements ExpressionToTerm<T> {
+ @SuppressWarnings("unchecked")
+ public RDFTerm map(Expression expr, FilterMapper parent) throws MulgaraParserException { return typedMap((T)expr, parent); }
+ }
+
+ /** A mapping of Expression types to constructors for the Filters they map to. */
+ private static Map<Class<? extends Expression>,ExpressionToTerm<? extends Expression>> mappers = new HashMap<Class<? extends Expression>,ExpressionToTerm<? extends Expression>>();
+
+ /**
+ * A utility method to add ExpressionToFilter mappers to the {@link #mappers} map.
+ * @param mapper The mapper to add.
+ */
+ private static void addToMap(ExpressionToTerm<? extends Expression> mapper) {
+ mappers.put(mapper.getMapType(), mapper);
+ }
+
+ // initialize the mappers
+ static {
+ addToMap(new BooleanMap());
+ addToMap(new IntegerMap());
+ addToMap(new DecimalMap());
+ addToMap(new DoubleMap());
+ addToMap(new VariableMap());
+ addToMap(new RDFLiteralMap());
+ addToMap(new IRIReferenceMap());
+ addToMap(new FunctionCallMap());
+ addToMap(new UnaryPlusMap());
+ addToMap(new UnaryMinusMap());
+ addToMap(new PlusMap());
+ addToMap(new MinusMap());
+ addToMap(new MultiplyMap());
+ addToMap(new DivideMap());
+ }
+
+ private static class BooleanMap extends AbstractExprToFilter<BooleanLiteral> {
+ public Class<BooleanLiteral> getMapType() { return BooleanLiteral.class; }
+ public RDFTerm typedMap(BooleanLiteral expr, FilterMapper parent) {
+ return expr == BooleanLiteral.TRUE ? Bool.TRUE : Bool.FALSE;
+ }
+ }
+
+ private static class IntegerMap extends AbstractExprToFilter<IntegerLiteral> {
+ public Class<IntegerLiteral> getMapType() { return IntegerLiteral.class; }
+ public RDFTerm typedMap(IntegerLiteral expr, FilterMapper parent) {
+ return new NumericLiteral(expr.getInteger());
+ }
+ }
+
+ private static class DecimalMap extends AbstractExprToFilter<DecimalLiteral> {
+ public Class<DecimalLiteral> getMapType() { return DecimalLiteral.class; }
+ public RDFTerm typedMap(DecimalLiteral expr, FilterMapper parent) {
+ return new NumericLiteral(expr.getFloat());
+ }
+ }
+
+ private static class DoubleMap extends AbstractExprToFilter<DoubleLiteral> {
+ public Class<DoubleLiteral> getMapType() { return DoubleLiteral.class; }
+ public RDFTerm typedMap(DoubleLiteral expr, FilterMapper parent) {
+ return new NumericLiteral(expr.getDouble());
+ }
+ }
+
+ private static class VariableMap extends AbstractExprToFilter<Variable> {
+ public Class<Variable> getMapType() { return Variable.class; }
+ public RDFTerm typedMap(Variable expr, FilterMapper parent) {
+ return new Var(expr.getName());
+ }
+ }
+
+ private static class RDFLiteralMap extends AbstractExprToFilter<RDFLiteral> {
+ public Class<RDFLiteral> getMapType() { return RDFLiteral.class; }
+ public RDFTerm typedMap(RDFLiteral expr, FilterMapper parent) {
+ if (expr.isTyped()) return TypedLiteral.newLiteral(expr.getValue(), expr.getDatatype().getUri(), null);
+ if (expr.isLanguageCoded()) return new SimpleLiteral(expr.getValue(), expr.getLanguage());
+ return new SimpleLiteral(expr.getValue());
+ }
+ }
+
+ private static class IRIReferenceMap extends AbstractExprToFilter<IRIReference> {
+ public Class<IRIReference> getMapType() { return IRIReference.class; }
+ public RDFTerm typedMap(IRIReference expr, FilterMapper parent) {
+ return new IRI(expr.getUri());
+ }
+ }
+
+ private static class FunctionCallMap extends AbstractExprToFilter<FunctionCall> {
+ public Class<FunctionCall> getMapType() { return FunctionCall.class; }
+ public RDFTerm typedMap(FunctionCall expr, FilterMapper parent) throws MulgaraParserException {
+ List<Expression> exprArgs = expr.getArgs();
+ RDFTerm[] operands = new RDFTerm[exprArgs.size()];
+ for (int i = 0; i < operands.length; i++) operands[i] = parent.mapExpression(exprArgs.get(i));
+ return new ExternalFn(new IRI(expr.getName().getUri()), operands);
+ }
+ }
+
+ private static class UnaryPlusMap extends AbstractExprToFilter<UnaryPlus> {
+ public Class<UnaryPlus> getMapType() { return UnaryPlus.class; }
+ public RDFTerm typedMap(UnaryPlus expr, FilterMapper parent) throws MulgaraParserException {
+ return parent.mapExpression(expr.getOperand());
+ }
+ }
+
+ private static class UnaryMinusMap extends AbstractExprToFilter<UnaryMinus> {
+ public Class<UnaryMinus> getMapType() { return UnaryMinus.class; }
+ public RDFTerm typedMap(UnaryMinus expr, FilterMapper parent) throws MulgaraParserException {
+ RDFTerm param = parent.mapExpression(expr.getOperand());
+ if (!(param instanceof NumericLiteral)) throw new MulgaraParserException("Cannot negate a non-number: " + param.getClass().getSimpleName());
+ return new org.mulgara.query.filter.arithmetic.UnaryMinus((NumericLiteral)param);
+ }
+ }
+
+ private static class PlusMap extends AbstractExprToFilter<Plus> {
+ public Class<Plus> getMapType() { return Plus.class; }
+ public RDFTerm typedMap(Plus expr, FilterMapper parent) throws MulgaraParserException {
+ return AddOperation.newAddOperation(parent.mapNumbers(expr.getOperands()));
+ }
+ }
+
+ private static class MinusMap extends AbstractExprToFilter<Minus> {
+ public Class<Minus> getMapType() { return Minus.class; }
+ public RDFTerm typedMap(Minus expr, FilterMapper parent) throws MulgaraParserException {
+ return MinusOperation.newMinusOperation(parent.mapNumbers(expr.getOperands()));
+ }
+ }
+
+ private static class MultiplyMap extends AbstractExprToFilter<Multiply> {
+ public Class<Multiply> getMapType() { return Multiply.class; }
+ public RDFTerm typedMap(Multiply expr, FilterMapper parent) throws MulgaraParserException {
+ return MultiplyOperation.newMultiplyOperation(parent.mapNumbers(expr.getOperands()));
+ }
+ }
+
+ private static class DivideMap extends AbstractExprToFilter<Divide> {
+ public Class<Divide> getMapType() { return Divide.class; }
+ public RDFTerm typedMap(Divide expr, FilterMapper parent) throws MulgaraParserException {
+ return DivideOperation.newDivideOperation(parent.mapNumbers(expr.getOperands()));
+ }
+ }
+
+}
More information about the Mulgara-svn
mailing list