/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.jena.arq.querybuilder.handlers; import java.io.StringReader; import java.util.List; import java.util.Map; import org.apache.jena.graph.Node; import org.apache.jena.query.Query; import org.apache.jena.query.QueryParseException; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.core.VarExprList; import org.apache.jena.sparql.expr.Expr; import org.apache.jena.sparql.lang.arq.ARQParser; import org.apache.jena.sparql.lang.arq.ParseException; import org.apache.jena.sparql.lang.arq.TokenMgrError; /** * A Select clause handler. * */ public class SelectHandler implements Handler { // the query to handle private final Query query; private final AggregationHandler aggHandler; /** * Constructor. * * @param aggHandler The aggregate handler that wraps the query we want to handle. */ public SelectHandler(AggregationHandler aggHandler) { this.query = aggHandler.getQuery(); this.aggHandler = aggHandler; setDistinct(query.isDistinct()); setReduced(query.isReduced()); } /** * Set the distinct flag. Set or unset the distinct flag. Will set the * reduced flag if it was previously set. * * @param state * the state to set the distinct flag to. */ public void setDistinct(boolean state) { query.setDistinct(state); if (state) { query.setReduced(false); } } /** * Set the reduced flag. Set or unset the reduced flag. Will set the reduced * flag if it was previously set. * * @param state * the state to set the reduced flag to. */ public void setReduced(boolean state) { query.setReduced(state); if (state) { query.setDistinct(false); } } /** * Add a variable to the select. If the variable is <code>null</code> the * variables are set to star. * * @param var * The variable to add. */ public void addVar(Var var) { if (var == null) { query.setQueryResultStar(true); } else { query.setQueryResultStar(false); query.addResultVar(var); } } /** * Add an Expression as variable to the select. If the variable is the * variables are set to star. * * @param expression * The expression as a string. * @param var * The variable to add. */ public void addVar(String expression, Var var) { addVar(parseExpr(expression), var); } /** * Parse an expression string into an expression. * * This must be able to be parsed as though it were written "SELECT "+s * * @param s * the select string to parse. * @return the epxression * @throws QueryParseException * on error */ private Expr parseExpr(String s) throws QueryParseException { try { ARQParser parser = new ARQParser(new StringReader("SELECT " + s)); parser.setQuery(new Query()); parser.getQuery().setPrefixMapping( query.getPrefixMapping()); parser.SelectClause(); Query q = parser.getQuery(); VarExprList vel = q.getProject(); return vel.getExprs().values().iterator().next(); } catch (ParseException ex) { throw new QueryParseException(ex.getMessage(), ex.currentToken.beginLine, ex.currentToken.beginLine); } catch (TokenMgrError tErr) { throw new QueryParseException(tErr.getMessage(), -1, -1); } catch (Error err) { // The token stream can throw java.lang.Error's String tmp = err.getMessage(); if (tmp == null) throw new QueryParseException(err, -1, -1); throw new QueryParseException(tmp, -1, -1); } } /** * Add an Expression as variable to the select. * * @param expr * The expression to add. * @param var * The variable to add. */ public void addVar(Expr expr, Var var) { if (expr == null) { throw new IllegalArgumentException("expr may not be null"); } if (var == null) { throw new IllegalArgumentException("var may not be null"); } query.setQueryResultStar(false); query.addResultVar(var, expr); aggHandler.add( expr, var ); } /** * Get the list of variables from the query. * * @return The list of variables in the query. */ public List<Var> getVars() { return query.getProjectVars(); } /** * Return the projected var expression list. * * @return The projected var expression list. */ public VarExprList getProject() { return query.getProject(); } /** * Add all the variables from the select handler variable. * * @param selectHandler * The select handler to copy the variables from. */ public void addAll(SelectHandler selectHandler) { setReduced(selectHandler.query.isReduced()); setDistinct(selectHandler.query.isDistinct()); query.setQueryResultStar(selectHandler.query.isQueryResultStar()); VarExprList shProjectVars = selectHandler.query.getProject(); VarExprList qProjectVars = query.getProject(); for (Var var : shProjectVars.getVars()) { // make sure there are no duplicates if (!qProjectVars.contains(var)) { qProjectVars.add(var, shProjectVars.getExpr(var)); } } aggHandler.addAll( selectHandler.aggHandler ); } @Override public void setVars(Map<Var, Node> values) { // nothing to do } @Override public void build() { if (query.getProject().getVars().isEmpty()) { query.setQueryResultStar(true); } aggHandler.build(); // handle the SELECT * case query.getProjectVars(); } }