/*
* Copyright 2009 Niclas Hedhman.
*
* 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 org.qi4j.index.rdf.query;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.openrdf.query.QueryLanguage;
import org.qi4j.api.query.grammar.OrderBy;
import org.qi4j.spi.query.NamedQueryDescriptor;
public class NamedSparqlDescriptor
implements NamedQueryDescriptor, Serializable
{
private static final List<String> EMPTY_LIST = new ArrayList<String>();
private String query;
private String name;
private List<String> variableNames = new ArrayList<String>();
public NamedSparqlDescriptor( String name, String query )
{
if( name == null )
{
throw new NullPointerException( "Queries must have a name" );
}
if( query == null )
{
throw new NullPointerException( "Null queries are not allowed" );
}
if( query.length() == 0 )
{
throw new IllegalArgumentException( "Empty query strings are not allowed." );
}
this.name = name;
this.query = query;
Matcher variableMatcher = Pattern.compile("\\?([\\p{Alpha}]*)").matcher(query);
while (variableMatcher.find())
{
String variableName = variableMatcher.group(1);
if (!variableNames.contains(variableName))
variableNames.add(variableName);
}
}
public String name()
{
return name;
}
public String compose( Map<String, Object> variables,
OrderBy[] orderBySegments,
Integer firstResult,
Integer maxResults
)
{
processOrderBy( orderBySegments );
StringBuffer s = new StringBuffer();
s.append( query );
s.append( " " );
s.append( range( firstResult, maxResults ) );
return s.toString();
}
public String language()
{
return QueryLanguage.SPARQL.getName();
}
public List<String> variableNames()
{
return variableNames;
}
private String range( Integer firstResult, Integer maxResults )
{
StringBuffer s = new StringBuffer();
if( maxResults != null && maxResults > 0 )
{
s.append( "LIMIT " );
s.append( maxResults );
s.append( '\n' );
}
if( firstResult != null && firstResult > 0 )
{
s.append( " OFFSET " );
s.append( firstResult );
s.append( '\n' );
}
return s.toString();
}
private void processOrderBy( OrderBy[] orderBySegments )
{
if( orderBySegments == null )
{
return;
}
String keyLocator = "ORDER BY ";
int pos = query.indexOf( keyLocator ) + keyLocator.length();
for( OrderBy order : orderBySegments )
{
while( Character.isWhitespace( query.charAt( pos ) ) )
{
pos = pos + 1;
}
String existing = query.substring( pos, pos + 4 ).toUpperCase();
if( existing.startsWith( "ASC" ) && order.order().equals( OrderBy.Order.DESCENDING ) )
{
String pre = query.substring( 0, pos );
String post = query.substring( pos + 3 );
query = pre + "DESC" + post;
}
else if( existing.startsWith( "DESC" ) && order.order().equals( OrderBy.Order.ASCENDING ) )
{
String pre = query.substring( 0, pos );
String post = query.substring( pos + 4 );
query = pre + "ASC" + post;
}
while( query.charAt( pos ) != ')' )
{
pos = pos + 1;
}
pos++;
}
}
}