blob: b29f586320c397837829b8faf4ae5ae0c64af55e [file] [log] [blame]
/*
* 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.sparql.core ;
import java.util.Objects;
import org.apache.jena.atlas.lib.Lib ;
import org.apache.jena.query.Query ;
import org.apache.jena.query.QueryVisitor ;
import org.apache.jena.sparql.util.NodeIsomorphismMap ;
// Two queries comparison
public class QueryCompare implements QueryVisitor
{
private Query query2 ;
private boolean result = true ;
static public boolean PrintMessages = false ;
public static boolean equals(Query query1, Query query2)
{
if ( query1 == query2 ) return true ;
query1.setResultVars() ;
query2.setResultVars() ;
QueryCompare visitor = new QueryCompare(query1) ;
try {
query2.visit(visitor) ;
} catch ( ComparisonException ex)
{
return false ;
}
return visitor.isTheSame() ;
}
public QueryCompare(Query query2)
{
this.query2 = query2 ;
}
@Override
public void startVisit(Query query1)
{ }
@Override
public void visitResultForm(Query query1)
{ check("Query result form", query1.queryType() == query2.queryType()) ; }
@Override
public void visitPrologue(Prologue query1)
{
check("Prefixes/Base", query1.samePrologue(query2) ) ;
}
@Override
public void visitSelectResultForm(Query query1)
{
check("Not both SELECT queries", query2.isSelectType()) ;
check("DISTINCT modifier",
query1.isDistinct() == query2.isDistinct()) ;
check("SELECT *", query1.isQueryResultStar() == query2.isQueryResultStar()) ;
check("Result variables", query1.getProject(), query2.getProject() ) ;
}
@Override
public void visitConstructResultForm(Query query1)
{
check("Not both CONSTRUCT queries", query2.isConstructType()) ;
check("CONSTRUCT templates",
query1.getConstructTemplate().equalIso(query2.getConstructTemplate(), new NodeIsomorphismMap()) ) ;
}
@Override
public void visitDescribeResultForm(Query query1)
{
check("Not both DESCRIBE queries", query2.isDescribeType()) ;
check("Result variables",
query1.getResultVars(), query2.getResultVars() ) ;
check("Result URIs",
query1.getResultURIs(), query2.getResultURIs() ) ;
}
@Override
public void visitAskResultForm(Query query1)
{
check("Not both ASK queries", query2.isAskType()) ;
}
@Override
public void visitJsonResultForm(Query query) {
check("Not both JSON queries", query2.isJsonType()) ;
}
@Override
public void visitDatasetDecl(Query query1)
{
boolean b1 = Lib.equalsListAsSet(query1.getGraphURIs(), query2.getGraphURIs()) ;
check("Default graph URIs", b1 ) ;
boolean b2 = Lib.equalsListAsSet(query1.getNamedGraphURIs(), query2.getNamedGraphURIs()) ;
check("Named graph URIs", b2 ) ;
}
@Override
public void visitQueryPattern(Query query1)
{
if ( query1.getQueryPattern() == null &&
query2.getQueryPattern() == null )
return ;
if ( query1.getQueryPattern() == null ) throw new ComparisonException("Missing pattern") ;
if ( query2.getQueryPattern() == null ) throw new ComparisonException("Missing pattern") ;
// The checking for patterns (elements) involves a potential
// remapping of system-allocated variable names.
// Assumes blank node variables only appear in patterns.
check("Pattern", query1.getQueryPattern().equalTo(query2.getQueryPattern(), new NodeIsomorphismMap())) ;
}
@Override
public void visitGroupBy(Query query1)
{
check("GROUP BY", query1.getGroupBy(), query2.getGroupBy()) ;
}
@Override
public void visitHaving(Query query1)
{
check("HAVING", query1.getHavingExprs(), query2.getHavingExprs()) ;
}
@Override
public void visitLimit(Query query1)
{
check("LIMIT", query1.getLimit() == query2.getLimit() ) ;
}
@Override
public void visitOrderBy(Query query1)
{
check("ORDER BY", query1.getOrderBy(), query2.getOrderBy() ) ;
}
@Override
public void visitOffset(Query query1)
{
check("OFFSET", query1.getOffset() == query2.getOffset() ) ;
}
@Override
public void visitValues(Query query1)
{
// Must be same order for now.
check("VALUES/variables", query1.getValuesVariables(), query2.getValuesVariables()) ;
check("VALUES/values", query1.getValuesData(), query2.getValuesData()) ;
}
@Override
public void finishVisit(Query query1)
{}
private void check(String msg, Object obj1, Object obj2)
{
check(msg, Objects.equals(obj1,obj2)) ;
}
private void check(String msg, boolean b)
{
if ( !b )
{
if ( PrintMessages && msg != null )
System.out.println("Different: "+msg) ;
result = false ;
throw new ComparisonException(msg) ;
}
}
public boolean isTheSame() { return result ; }
}