package org.weso.wesearch.domain.impl;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.Set;
import org.apache.log4j.Logger;
import org.weso.utils.QueryBuilderException;
import org.weso.utils.WesearchException;
import org.weso.wesearch.domain.Query;
import org.weso.wesearch.domain.impl.filters.Filter;
import org.weso.wesearch.domain.impl.filters.Filters;
import org.weso.wesearch.domain.impl.filters.Operator;
import org.weso.wesearch.domain.impl.filters.SPARQLFilter;
import org.weso.wesearch.domain.impl.filters.SPARQLFilters;
import weso.mediator.config.Configuration;
/**
* It's an implementation of the interface Query that represents SPARQL queries
*/
public class SPARQLQuery implements Query {
private static Logger logger = Logger.getLogger(SPARQLQuery.class);
/**
* A list of variable to use in the queries
*/
private static List<String> variables = null;
/**
* A map that a contains a relantion between a variable and a filter that
* are applied over the variable
*/
private Map<String, Filters> filters;
/**
* A list of clauses that form the query
*/
private List<String> clauses;
/**
* Is the position in the list of the next variable to use in the query
*/
private int nextVar;
/**
* The string form of the query
*/
private String query;
/**
* It's the constructor of the class
* @throws IOException This exception is thrown if there is a problem
* reading the file that contains the name of the variables to use in the
* queries
*/
public SPARQLQuery() throws IOException {
filters = new HashMap<String, Filters>();
clauses = new LinkedList<String>();
nextVar = -1;
if(variables == null) {
readVariableFromProperties();
}
query = "";
}
/**
* This method has to load variables to use in the queries form the file
* which path is in properties file
* @throws IOException This exception is thrown if there is a problem
* reading the variables from file
*/
private void readVariableFromProperties() throws IOException {
InputStream input = Configuration.getLocalStream(
Configuration.getProperty("sparql_variables"));
if(input == null)
throw new IOException("There was a problem reading variables");
ResourceBundle var = new PropertyResourceBundle(input);
variables = new LinkedList<String>(var.keySet());
Collections.sort(variables);
}
@Override
public String obtainQuery() {
String query = "SELECT DISTINCT ?res WHERE { ";
query += generateClausesString();
query += generateFilterClausesString();
query += "}";
return query;
}
/**
* This method concatenates all filter clauses of the query
* @return A string that concatenates the filter clauses
*/
private String generateFilterClausesString() {
String query = "";
for(String key : filters.keySet()) {
Filters filters = this.filters.get(key);
if(filters != null) {
query += "FILTER( " + filters.toString() + " ) .";
}
}
return query;
}
/**
* This method concatenates all clauses (except filter clauses) of the query
* @return A string that concatenates the clauses
*/
private String generateClausesString() {
String query = "";
for(String clause : clauses) {
query += clause + " . ";
}
return query;
}
@Override
public void addClause(String clause) {
if(clause != null) {
clauses.add(clause);
}
}
@Override
public void addFilters(String varName, Filters filter)
throws QueryBuilderException {
if(varName == null || filter == null) {
logger.error("Some part of the query are null");
throw new QueryBuilderException("Some part of the query are null");
}
filters.put(varName, filter);
}
@Override
public void addFilter(String varName, Filter filter)
throws QueryBuilderException {
if(varName == null) {
logger.error("Some part of the query are null");
throw new QueryBuilderException("Some part of the query are null");
}
if(filter == null) {
filters.put(varName, null);
} else {
concatFilterVariable(varName, filter);
}
}
/**
* This method concatenates a new filter to others that already filter a
* variable in the query
* @param varName The name of the variable that has to be filtered
* @param filter The new filter to add
*/
private void concatFilterVariable(String varName, Filter filter) {
Filters fil = filters.get(varName);
if(fil == null ) {
SPARQLFilters sparqlFilters = new SPARQLFilters(
(SPARQLFilter)filter);
filters.put(varName, sparqlFilters);
} else {
fil.addFilter(filter, Operator.AND);
}
}
@Override
public String getNextVarName() throws WesearchException {
nextVar++;
if(nextVar >= 0 && nextVar < variables.size()) {
return variables.get(nextVar);
}
logger.error("Index for next variable incorrect");
throw new WesearchException("Index for next variable incorrect");
}
@Override
public boolean isPropertyForResult() {
Set<String> keys = filters.keySet();
for(String key : keys) {
if(filters.get(key) == null) {
return false;
}
}
return true;
}
@Override
public String obtainAuxiliarVarName() {
Set<String> keys = filters.keySet();
for(String key : keys) {
if(filters.get(key) == null) {
return key;
}
}
throw new RuntimeException("There isn't any auxiliar variable that " +
"it isn't typed");
}
/**
* This method returns the list of variables
* @return The list of variables to use in the query
*/
public static List<String> getVariables() {
return variables;
}
/**
* This method sets a new list of variables
* @param variables The new list of variables
*/
public static void setVariables(List<String> variables) {
SPARQLQuery.variables = variables;
}
/**
* This method returns the map that contains the relations between variables
* and filters
* @return A map with the relations between variables and filters
*/
public Map<String, Filters> getFilters() {
return filters;
}
/**
* This method sets a new map with the relation between variables and them
* filters
* @param filters The new map
*/
public void setFilters(Map<String, Filters> filters) {
this.filters = filters;
}
/**
* This method return the list of clauses of the query
* @return The list of clauses
*/
public List<String> getClauses() {
return clauses;
}
/**
* This method sets a new list of clauses
* @param clauses The new list of clauses of the query
*/
public void setClauses(List<String> clauses) {
this.clauses = clauses;
}
/**
* This method returns the position of the next variable to use in the query
* @return The position in the list of the next variable to use in the query
*/
public int getNextVar() {
return nextVar;
}
/**
* This method sets a new position in the list for the next variable to use
* @param nextVar The position in the list of the next var
*/
public void setNextVar(int nextVar) {
this.nextVar = nextVar;
}
/**
* This method returns the string of the SPARQL query
* @return The string of the SPARQL query
*/
public String getQuery() {
query = obtainQuery();
return query;
}
/**
* This method sets a new string to the query
* @param query The new string to the query
*/
public void setQuery(String query) {
this.query = query;
}
}