![JAR search and dependency download from the Maven repository](/logo.png)
com.clarkparsia.pellet.sparqldl.parser.ARQParser Maven / Gradle / Ivy
// Copyright (c) 2006 - 2008, Clark & Parsia, LLC.
// This source code is available under the terms of the Affero General Public
// License v3.
//
// Please see LICENSE.txt for full license terms, including the availability of
// proprietary exceptions.
// Questions, comments, or requests for clarification: [email protected]
package com.clarkparsia.pellet.sparqldl.parser;
import static com.clarkparsia.pellet.utils.TermFactory.BOTTOM;
import static com.clarkparsia.pellet.utils.TermFactory.BOTTOM_DATA_PROPERTY;
import static com.clarkparsia.pellet.utils.TermFactory.BOTTOM_OBJECT_PROPERTY;
import static com.clarkparsia.pellet.utils.TermFactory.TOP;
import static com.clarkparsia.pellet.utils.TermFactory.TOP_DATA_PROPERTY;
import static com.clarkparsia.pellet.utils.TermFactory.TOP_OBJECT_PROPERTY;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.mindswap.pellet.KnowledgeBase;
import org.mindswap.pellet.PelletOptions;
import org.mindswap.pellet.PropertyType;
import org.mindswap.pellet.Role;
import org.mindswap.pellet.exceptions.UnsupportedFeatureException;
import org.mindswap.pellet.exceptions.UnsupportedQueryException;
import org.mindswap.pellet.jena.BuiltinTerm;
import org.mindswap.pellet.jena.JenaUtils;
import org.mindswap.pellet.jena.vocabulary.OWL2;
import org.mindswap.pellet.utils.ATermUtils;
import aterm.ATerm;
import aterm.ATermAppl;
import aterm.ATermList;
import com.clarkparsia.pellet.sparqldl.model.Query;
import com.clarkparsia.pellet.sparqldl.model.Query.VarType;
import com.clarkparsia.pellet.sparqldl.model.QueryAtomFactory;
import com.clarkparsia.pellet.sparqldl.model.QueryImpl;
import com.clarkparsia.pellet.utils.TermFactory;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.QuerySolutionMap;
import com.hp.hpl.jena.query.Syntax;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.sparql.core.BasicPattern;
import com.hp.hpl.jena.sparql.core.TriplePath;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.syntax.Element;
import com.hp.hpl.jena.sparql.syntax.ElementGroup;
import com.hp.hpl.jena.sparql.syntax.ElementPathBlock;
import com.hp.hpl.jena.sparql.syntax.ElementTriplesBlock;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
/**
*
* Title: Parser for the SPARQL-DL based on ARQ
*
*
* Description: Meanwhile does not deal with types of variables.
*
*
* Copyright: Copyright (c) 2007
*
*
* Company: Clark & Parsia, LLC.
*
*
* @author Petr Kremen
*/
public class ARQParser implements QueryParser {
public static Logger log = Logger.getLogger( ARQParser.class.getName() );
private Set triples;
private Map terms;
private KnowledgeBase kb;
private QuerySolution initialBinding;
/*
* If this variable is true then queries with variable SPO statements are
* not handled by the SPARQL-DL engine but fall back to ARQ
*/
private boolean handleVariableSPO = true;
public ARQParser() {
this( true );
}
public ARQParser(boolean handleVariableSPO) {
this.handleVariableSPO = handleVariableSPO;
}
/**
* {@inheritDoc}
*/
public Query parse(InputStream stream, KnowledgeBase kb) {
try {
return parse( new InputStreamReader( stream ), kb );
} catch( IOException e ) {
final String message = "Error creating a reader from the input stream.";
log.severe( message );
throw new RuntimeException( message );
}
}
/**
* {@inheritDoc}
*/
public Query parse(String queryStr, KnowledgeBase kb) {
com.hp.hpl.jena.query.Query sparql = QueryFactory.create( queryStr, Syntax.syntaxSPARQL );
return parse( sparql, kb );
}
private Query parse(Reader in, KnowledgeBase kb) throws IOException {
StringBuffer queryString = new StringBuffer();
BufferedReader r = new BufferedReader( in );
String line = r.readLine();
while( line != null ) {
queryString.append( line ).append( "\n" );
line = r.readLine();
}
return parse( queryString.toString(), kb );
}
public Query parse(com.hp.hpl.jena.query.Query sparql, KnowledgeBase kb) {
this.kb = kb;
if( sparql.isDescribeType() )
throw new UnsupportedQueryException(
"DESCRIBE queries cannot be answered with PelletQueryEngine" );
final Element pattern = sparql.getQueryPattern();
if( !(pattern instanceof ElementGroup) )
throw new UnsupportedQueryException( "ElementGroup was expected, but found '"
+ pattern.getClass() + "'." );
final ElementGroup elementGroup = (ElementGroup) pattern;
final List elements = elementGroup.getElements();
final Element first = elements.get( 0 );
if (elements.size() != 1 || (!(first instanceof ElementTriplesBlock) && !(first instanceof ElementPathBlock)))
throw new UnsupportedQueryException("Complex query patterns are not supported yet.");
List triples;
if (first instanceof ElementPathBlock) {
triples = new ArrayList();
for (TriplePath path : ((ElementPathBlock) first).getPattern()) {
if (!path.isTriple()) {
throw new UnsupportedQueryException("Path expressions are not supported yet.");
}
triples.add(path.asTriple());
}
}
else {
triples = ((ElementTriplesBlock) first).getPattern().getList();
}
// very important to call this function so that getResultVars() will
// work fine for SELECT * queries
sparql.setResultVars();
return parse( triples, sparql.getResultVars(), kb, sparql.isDistinct() );
}
private void initBuiltinTerms() {
terms = new HashMap();
terms.put( OWL.Thing.asNode(), TOP );
terms.put( OWL.Nothing.asNode(), BOTTOM );
terms.put( OWL2.topObjectProperty.asNode(), TOP_OBJECT_PROPERTY );
terms.put( OWL2.topDataProperty.asNode(), TOP_DATA_PROPERTY );
terms.put( OWL2.bottomObjectProperty.asNode(), BOTTOM_OBJECT_PROPERTY );
terms.put( OWL2.bottomDataProperty.asNode(), BOTTOM_DATA_PROPERTY );
}
public Query parse(BasicPattern basicPattern, Collection> resultVars, KnowledgeBase kb,
boolean isDistinct) throws UnsupportedQueryException {
return parse(basicPattern.getList(), resultVars, kb, isDistinct);
}
public Query parse(List basicPattern, Collection> resultVars, KnowledgeBase kb,
boolean isDistinct) throws UnsupportedQueryException {
this.kb = kb;
// This set contains predicates that are distinguished variables. The
// elements are accumulated for PropertyValueAtom and removed if used in
// subject position of other SPARQL-DL query atoms. If the set
// is not empty, we throw an unsupported query exception and fall back
// to ARQ to process the query. This solves the problem of {} ?p {}
// queries where ?p is not used as subject in other patterns
Set variablePredicates = new HashSet();
// This set contains subjects that are distinguished variables and is
// used to collect variables along the way while processing triple
// patterns. The list is used to decide whether or not the variable
// property of a pattern {} ?p {} has to be accumulated to the
// variablePredicates set. This avoids to add them for the case where
// the variable in predicate position is bound to a subject of another
// triple pattern, e.g. ?p rdf:type owl:ObjectProperty . ?s ?p ?o
Set variableSubjects = new HashSet();
initBuiltinTerms();
// Make sure to resolve the query parameterization first, i.e.
// substitute the variables with initial bindings, if applicable
triples = new LinkedHashSet( resolveParameterization( basicPattern ) );
final Query query = new QueryImpl( kb, isDistinct );
for( Iterator> i = resultVars.iterator(); i.hasNext(); ) {
String var = (String) i.next();
query.addResultVar( ATermUtils.makeVar( var ) );
}
for( final Triple t : new ArrayList( triples ) ) {
if( !triples.contains( t ) ) {
continue;
}
Node subj = t.getSubject();
Node pred = t.getPredicate();
Node obj = t.getObject();
if (BuiltinTerm.isSyntax(pred) || BuiltinTerm.isSyntax(obj))
continue;
cache( subj );
cache( pred );
cache( obj );
}
final Set possibleLiteralVars = new HashSet();
//throw exception if triples is empty
if(triples.isEmpty()){
throw new UnsupportedQueryException(
"Empty BGT" );
}
for( final Triple t : triples ) {
Node subj = t.getSubject();
Node pred = t.getPredicate();
Node obj = t.getObject();
ATermAppl s = (ATermAppl) terms.get( subj );
ATermAppl p = (ATermAppl) terms.get( pred );
ATermAppl o = (ATermAppl) terms.get( obj );
if( pred.equals( RDF.Nodes.type ) ) {
// Map ?c rdf:type owl:Class to SubClassOf(?c owl:Thing)
if( obj.equals( OWL.Class.asNode() ) ) {
query.add( QueryAtomFactory.SubClassOfAtom( s, TermFactory.TOP ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
}
//NamedIndividual(p)
else if( obj.equals( OWL2.NamedIndividual.asNode() ) ) {
query.add( QueryAtomFactory.TypeAtom(s, TermFactory.TOP ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
}
// ObjectProperty(p)
else if( obj.equals( OWL.ObjectProperty.asNode() ) ) {
query.add( QueryAtomFactory.ObjectPropertyAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// DatatypeProperty(p)
else if( obj.equals( OWL.DatatypeProperty.asNode() ) ) {
query.add( QueryAtomFactory.DatatypePropertyAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Property(p)
else if( obj.equals( RDF.Property.asNode() ) ) {
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Functional(p)
else if( obj.equals( OWL.FunctionalProperty.asNode() ) ) {
query.add( QueryAtomFactory.FunctionalAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// InverseFunctional(p)
else if( obj.equals( OWL.InverseFunctionalProperty.asNode() ) ) {
query.add( QueryAtomFactory.InverseFunctionalAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Transitive(p)
else if( obj.equals( OWL.TransitiveProperty.asNode() ) ) {
query.add( QueryAtomFactory.TransitiveAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Symmetric(p)
else if( obj.equals( OWL.SymmetricProperty.asNode() ) ) {
query.add( QueryAtomFactory.SymmetricAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Asymmetric(p)
else if( obj.equals( OWL2.AsymmetricProperty.asNode() ) ) {
query.add( QueryAtomFactory.AsymmetricAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Reflexive(p)
else if( obj.equals( OWL2.ReflexiveProperty.asNode() ) ) {
query.add( QueryAtomFactory.ReflexiveAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Irreflexive(p)
else if( obj.equals( OWL2.IrreflexiveProperty.asNode() ) ) {
query.add( QueryAtomFactory.IrreflexiveAtom( s ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
else {
ensureTypedProperty( s );
}
}
// Annotation(s,pa,o)
else if( hasObject( pred, RDF.type.asNode(), OWL.AnnotationProperty.asNode() ) ) {
query.add( QueryAtomFactory.AnnotationAtom( s, p, o ) );
if( ATermUtils.isVar( s ) || ATermUtils.isVar( p ) || ATermUtils.isVar( o ) ) {
throw new UnsupportedQueryException(
"Variables in annotation atom are not supported." );
}
else {
ensureTypedProperty( p );
}
}
// Type(i,c)
else {
query.add( QueryAtomFactory.TypeAtom( s, o ) );
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
else if( !kb.isClass( o ) ) {
if( log.isLoggable( Level.FINE ) )
log
.fine( "Class " + o
+ " used in the query is not defined in the KB." );
}
if( isDistinguishedVariable( subj ) ) {
query.addDistVar( s, VarType.INDIVIDUAL );
}
}
}
// SameAs(i1,i2)
else if( pred.equals( OWL.sameAs.asNode() ) ) {
query.add( QueryAtomFactory.SameAsAtom( s, o ) );
if( isDistinguishedVariable( subj ) ) {
query.addDistVar( s, VarType.INDIVIDUAL );
}
if( isDistinguishedVariable( obj ) ) {
query.addDistVar( o, VarType.INDIVIDUAL );
}
}
// DifferentFrom(i1,i2)
else if( pred.equals( OWL.differentFrom.asNode() ) ) {
query.add( QueryAtomFactory.DifferentFromAtom( s, o ) );
if( isDistinguishedVariable( subj ) ) {
query.addDistVar( s, VarType.INDIVIDUAL );
}
if( isDistinguishedVariable( obj ) ) {
query.addDistVar( o, VarType.INDIVIDUAL );
}
}
// SubClassOf(c1,c2)
else if( pred.equals( RDFS.subClassOf.asNode() ) ) {
query.add( QueryAtomFactory.SubClassOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
}
// strict subclass - nonmonotonic
else if( pred.equals( SparqldlExtensionsVocabulary.strictSubClassOf.asNode() ) ) {
query.add( QueryAtomFactory.StrictSubClassOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
}
// direct subclass - nonmonotonic
else if( pred.equals( SparqldlExtensionsVocabulary.directSubClassOf.asNode() ) ) {
query.add( QueryAtomFactory.DirectSubClassOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
}
// EquivalentClass(c1,c2)
else if( pred.equals( OWL.equivalentClass.asNode() ) ) {
query.add( QueryAtomFactory.EquivalentClassAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
}
// DisjointWith(c1,c2)
else if( pred.equals( OWL.disjointWith.asNode() ) ) {
query.add( QueryAtomFactory.DisjointWithAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
}
// ComplementOf(c1,c2)
else if( pred.equals( OWL.complementOf.asNode() ) ) {
query.add( QueryAtomFactory.ComplementOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.CLASS );
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
}
// propertyDisjointWith(p1,p2)
else if( pred.equals( OWL2.propertyDisjointWith.asNode() ) ) {
ensureTypedProperty( s );
ensureTypedProperty( o );
query.add( QueryAtomFactory.PropertyDisjointWithAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( o );
variableSubjects.add( o );
}
}
}
// SubPropertyOf(p1,p2)
else if( pred.equals( RDFS.subPropertyOf.asNode() ) ) {
ensureTypedProperty( s );
ensureTypedProperty( o );
query.add( QueryAtomFactory.SubPropertyOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( o );
variableSubjects.add( o );
}
}
}
// DirectSubPropertyOf(i,p) - nonmonotonic
else if( pred.equals( SparqldlExtensionsVocabulary.directSubPropertyOf.asNode() ) ) {
ensureTypedProperty( s );
ensureTypedProperty( o );
query.add( QueryAtomFactory.DirectSubPropertyOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( o );
variableSubjects.add( o );
}
}
}
// StrictSubPropertyOf(i,p) - nonmonotonic
else if( pred.equals( SparqldlExtensionsVocabulary.strictSubPropertyOf.asNode() ) ) {
ensureTypedProperty( s );
ensureTypedProperty( o );
query.add( QueryAtomFactory.StrictSubPropertyOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( o );
variableSubjects.add( o );
}
}
}
// EquivalentProperty(p1,p2)
else if( pred.equals( OWL.equivalentProperty.asNode() ) ) {
ensureTypedProperty( s );
ensureTypedProperty( o );
query.add( QueryAtomFactory.EquivalentPropertyAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( o );
variableSubjects.add( o );
}
}
}
// Domain(p1, c)
else if( pred.equals( RDFS.domain.asNode() ) ) {
ensureTypedProperty( s );
query.add( QueryAtomFactory.DomainAtom( s, o ) );
if ( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( s, VarType.CLASS );
}
}
// Range(p1, c)
else if( pred.equals( RDFS.range.asNode() ) ) {
ensureTypedProperty( s );
query.add( QueryAtomFactory.RangeAtom( s, o ) );
if ( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
// TODO it could also range over datatypes.
query.addDistVar( s, VarType.CLASS );
}
}
// InverseOf(p1,p2)
else if( pred.equals( OWL.inverseOf.asNode() ) ) {
ensureTypedProperty( s );
ensureTypedProperty( o );
query.add( QueryAtomFactory.InverseOfAtom( s, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( o );
variableSubjects.add( o );
}
}
}
// DirectType(i,c) - nonmonotonic
else if( pred.equals( SparqldlExtensionsVocabulary.directType.asNode() ) ) {
query.add( QueryAtomFactory.DirectTypeAtom( s, o ) );
if( isDistinguishedVariable( subj ) ) {
query.addDistVar( s, VarType.INDIVIDUAL );
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.CLASS );
}
}
else if( kb.isAnnotationProperty( p ) ) {
if( !PelletOptions.USE_ANNOTATION_SUPPORT ) {
throw new UnsupportedQueryException(
"Cannot answer annotation queries when PelletOptions.USE_ANNOTATION_SUPPORT is false!" );
}
query.add( QueryAtomFactory.AnnotationAtom( s, p, o ) );
if( ATermUtils.isVar( s ) ) {
ensureDistinguished( subj );
query.addDistVar( s, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( s );
variableSubjects.add( s );
}
}
if( ATermUtils.isVar( o ) ) {
ensureDistinguished( obj );
query.addDistVar( o, VarType.PROPERTY );
if( handleVariableSPO ) {
variablePredicates.remove( o );
variableSubjects.add( o );
}
}
// throw new UnsupportedQueryException(
// "Annotation properties are not supported in queries." );
}
// PropertyValue(i,p,j)
else {
if( s == null || p == null || o == null ) {
throw new UnsupportedQueryException("Atom conversion incomplete for: " + t);
}
ensureTypedProperty( p );
query.add( QueryAtomFactory.PropertyValueAtom( s, p, o ) );
if( ATermUtils.isVar( p ) ) {
ensureDistinguished( pred );
query.addDistVar( p, VarType.PROPERTY );
// If the predicate is a variable used in a subject position
// we don't have to consider it as it is bound to another
// triple pattern
if( !variableSubjects.contains( p ) )
variablePredicates.add( p );
}
if( isDistinguishedVariable( subj ) ) {
query.addDistVar( s, VarType.INDIVIDUAL );
}
if( isDistinguishedVariable( obj ) ) {
if( ATermUtils.isVar( p ) ) {
possibleLiteralVars.add( o );
}
else {
if( kb.isObjectProperty( p ) ) {
query.addDistVar( o, VarType.INDIVIDUAL );
}
else if( kb.isDatatypeProperty( p ) ) {
query.addDistVar( o, VarType.LITERAL );
}
}
}
}
}
for( final ATermAppl v : possibleLiteralVars ) {
if( !query.getDistVars().contains( v ) ) {
query.addDistVar( v, VarType.LITERAL );
}
query.addDistVar( v, VarType.INDIVIDUAL );
}
if( !handleVariableSPO )
return query;
if( variablePredicates.isEmpty() )
return query;
throw new UnsupportedQueryException( "Queries with variable predicates are not supported "
+ "(add the pattern {?p rdf:type owl:ObjectProperty} or"
+ " {?p rdf:type owl:DatatypeProperty} to the query)" );
}
public void setInitialBinding(QuerySolution initialBinding) {
this.initialBinding = initialBinding;
}
private void ensureDistinguished(Node pred) {
ensureDistinguished( pred,
"Non-distinguished variables in class and predicate positions are not supported : " );
}
private void ensureDistinguished(Node pred, String errorNonDist) {
if( !isDistinguishedVariable( pred ) ) {
throw new UnsupportedQueryException( errorNonDist + pred );
}
}
private void ensureTypedProperty( ATermAppl pred ) {
if ( ATermUtils.isVar( pred ) )
return;
Role r = kb.getRole( pred );
if ( r == null ) {
throw new UnsupportedQueryException( "Unknown role: " + pred );
}
if ( r.isUntypedRole() ) {
throw new UnsupportedQueryException( "Untyped role: " + pred );
}
}
public static boolean isDistinguishedVariable(final Node node) {
return Var.isVar( node )
&& (Var.isNamedVar( node ) || PelletOptions.TREAT_ALL_VARS_DISTINGUISHED);
}
private Node getObject(Node subj, Node pred) {
for( final Iterator i = triples.iterator(); i.hasNext(); ) {
Triple t = i.next();
if( subj.equals( t.getSubject() ) && pred.equals( t.getPredicate() ) ) {
i.remove();
return t.getObject();
}
}
return null;
}
private boolean hasObject(Node subj, Node pred) {
for( final Iterator i = triples.iterator(); i.hasNext(); ) {
Triple t = i.next();
if( subj.equals( t.getSubject() ) && pred.equals( t.getPredicate() ) )
return true;
}
return false;
}
private boolean hasObject(Node subj, Node pred, Node obj) {
for( final Iterator i = triples.iterator(); i.hasNext(); ) {
Triple t = i.next();
if( subj.equals( t.getSubject() ) && pred.equals( t.getPredicate() ) ) {
i.remove();
if( obj.equals( t.getObject() ) ) {
return true;
}
throw new UnsupportedQueryException( "Expecting rdf:type " + obj
+ " but found rdf:type " + t.getObject() );
}
}
return false;
}
private ATermList createList(Node node) {
if( node.equals( RDF.nil.asNode() ) )
return ATermUtils.EMPTY_LIST;
else if( terms.containsKey( node ) )
return (ATermList) terms.get( node );
hasObject( node, RDF.type.asNode(), RDF.List.asNode() );
Node first = getObject( node, RDF.first.asNode() );
Node rest = getObject( node, RDF.rest.asNode() );
if( first == null || rest == null ) {
throw new UnsupportedQueryException( "Invalid list structure: List " + node
+ " does not have a " + (first == null
? "rdf:first"
: "rdf:rest") + " property." );
}
ATermList list = ATermUtils.makeList( node2term( first ), createList( rest ) );
terms.put( node, list );
return list;
}
private ATermAppl createRestriction(Node node) throws UnsupportedFeatureException {
ATermAppl aTerm = ATermUtils.TOP;
hasObject( node, RDF.type.asNode(), OWL.Restriction.asNode() );
Node p = getObject( node, OWL.onProperty.asNode() );
// TODO warning message: no owl:onProperty
if( p == null )
return aTerm;
ATermAppl pt = node2term( p );
if( !kb.isProperty( pt ) )
throw new UnsupportedQueryException( "Property " + pt + " is not present in KB." );
// TODO warning message: multiple owl:onProperty
Node o = null;
if( (o = getObject( node, OWL.hasValue.asNode() )) != null ) {
if( PelletOptions.USE_PSEUDO_NOMINALS ) {
if( o.isLiteral() ) {
aTerm = ATermUtils.makeMin( pt, 1, ATermUtils.TOP_LIT );
}
else {
ATermAppl ind = ATermUtils.makeTermAppl( o.getURI() );
if( !kb.isIndividual( ind ) )
throw new UnsupportedQueryException( "Individual " + ind
+ " is not present in KB." );
ATermAppl nom = ATermUtils.makeTermAppl( o.getURI() + "_nom" );
aTerm = ATermUtils.makeSomeValues( pt, nom );
}
}
else {
ATermAppl ot = node2term( o );
aTerm = ATermUtils.makeHasValue( pt, ot );
}
}
else if( (o = getObject( node, OWL2.hasSelf.asNode() )) != null ) {
ATermAppl ot = node2term( o );
if( ATermUtils.isVar( ot ) )
throw new UnsupportedQueryException("Variables not supported in hasSelf restriction");
else
aTerm = ATermUtils.makeSelf(pt);
}
else if( (o = getObject( node, OWL.allValuesFrom.asNode() )) != null ) {
ATermAppl ot = node2term( o );
if( ATermUtils.isVar( ot ) )
throw new UnsupportedQueryException("Variables not supported in allValuesFrom restriction");
else
aTerm = ATermUtils.makeAllValues( pt, ot );
}
else if( (o = getObject( node, OWL.someValuesFrom.asNode() )) != null ) {
ATermAppl ot = node2term( o );
if( ATermUtils.isVar( ot ) )
throw new UnsupportedQueryException("Variables not supported in someValuesFrom restriction");
else
aTerm = ATermUtils.makeSomeValues( pt, ot );
}
else if( (o = getObject( node, OWL.minCardinality.asNode() )) != null ) {
aTerm = createCardinalityRestriction( node, OWL.minCardinality.asNode(), pt, o );
}
else if( (o = getObject( node, OWL2.minQualifiedCardinality.asNode() )) != null ) {
aTerm = createCardinalityRestriction( node, OWL2.minQualifiedCardinality.asNode(), pt, o );
}
else if( (o = getObject( node, OWL.maxCardinality.asNode() )) != null ) {
aTerm = createCardinalityRestriction( node, OWL.maxCardinality.asNode(), pt, o );
}
else if( (o = getObject( node, OWL2.maxQualifiedCardinality.asNode() )) != null ) {
aTerm = createCardinalityRestriction( node, OWL2.maxQualifiedCardinality.asNode(), pt, o );
}
else if( (o = getObject( node, OWL.cardinality.asNode() )) != null ) {
aTerm = createCardinalityRestriction( node, OWL.cardinality.asNode(), pt, o );
}
else if( (o = getObject( node, OWL2.qualifiedCardinality.asNode() )) != null ) {
aTerm = createCardinalityRestriction( node, OWL2.qualifiedCardinality.asNode(), pt, o );
}
else {
// TODO print warning message (invalid restriction type)
}
return aTerm;
}
private ATermAppl createCardinalityRestriction(Node node, Node restrictionType, ATermAppl pt, Node card)
throws UnsupportedQueryException {
try {
ATermAppl c = null;
Node qualification = null;
if( (qualification = getObject( node, OWL2.onClass.asNode() )) != null ) {
if( qualification.isVariable() ) {
throw new UnsupportedQueryException( "Variables not allowed in cardinality qualification" );
}
if( !kb.isObjectProperty( pt ) )
return null;
c = node2term( qualification );
}
else if( (qualification = getObject( node, OWL2.onDataRange.asNode() )) != null ) {
if( qualification.isVariable() ) {
throw new UnsupportedQueryException( "Variables not allowed in cardinality qualification" );
}
if( !kb.isDatatypeProperty( pt ) )
return null;
c = node2term( qualification );
}
else {
PropertyType propType = kb.getPropertyType( pt );
if( propType == PropertyType.OBJECT )
c = ATermUtils.TOP;
else if( propType == PropertyType.DATATYPE )
c = ATermUtils.TOP_LIT;
else
c = ATermUtils.TOP;
}
int cardinality = Integer.parseInt( card.getLiteralLexicalForm() );
if( restrictionType.equals( OWL.minCardinality.asNode() )
|| restrictionType.equals( OWL2.minQualifiedCardinality.asNode() ) )
return ATermUtils.makeMin( pt, cardinality, c );
else if( restrictionType.equals( OWL.maxCardinality.asNode() )
|| restrictionType.equals( OWL2.maxQualifiedCardinality.asNode() ) )
return ATermUtils.makeMax( pt, cardinality, c );
else
return ATermUtils.makeCard( pt, cardinality, c );
} catch( Exception ex ) {
log.log( Level.WARNING, "Invalid cardinality", ex );
}
return null;
}
private ATermAppl node2term(Node node) {
if(!terms.containsKey(node)) {
cache(node);
}
return (ATermAppl) terms.get( node );
}
private void cache(Node node) {
if(terms.containsKey(node) || BuiltinTerm.isBuiltin(node) ) {
return;
}
ATerm aTerm = null;
if( node.isLiteral() )
aTerm = JenaUtils.makeLiteral( node.getLiteral() );
else if( hasObject( node, OWL.onProperty.asNode() ) ) {
aTerm = createRestriction( node );
terms.put( node, aTerm );
}
else if( node.isBlank() || node.isVariable() ) {
Node o = null;
if( (o = getObject( node, OWL.intersectionOf.asNode() )) != null ) {
ATermList list = createList( o );
hasObject( node, RDF.type.asNode(), OWL.Class.asNode() );
aTerm = ATermUtils.makeAnd( list );
}
else if( (o = getObject( node, OWL.unionOf.asNode() )) != null ) {
ATermList list = createList( o );
hasObject( node, RDF.type.asNode(), OWL.Class.asNode() );
aTerm = ATermUtils.makeOr( list );
}
else if( (o = getObject( node, OWL.oneOf.asNode() )) != null ) {
ATermList list = createList( o );
hasObject( node, RDF.type.asNode(), OWL.Class.asNode() );
ATermList result = ATermUtils.EMPTY_LIST;
for( ATermList l = list; !l.isEmpty(); l = l.getNext() ) {
ATermAppl c = (ATermAppl) l.getFirst();
if( PelletOptions.USE_PSEUDO_NOMINALS ) {
ATermAppl nominal = ATermUtils.makeTermAppl( c.getName() + "_nominal" );
result = result.insert( nominal );
}
else {
ATermAppl nominal = ATermUtils.makeValue( c );
result = result.insert( nominal );
}
}
aTerm = ATermUtils.makeOr( result );
}
else if( Var.isBlankNodeVar( node )
&& (o = getObject( node, OWL.complementOf.asNode() )) != null ) {
ATermAppl complement = node2term( o );
hasObject( node, RDF.type.asNode(), OWL.Class.asNode() );
aTerm = ATermUtils.makeNot( complement );
}
else if( node.isVariable() ) {
aTerm = ATermUtils.makeVar( node.getName() );
}
else {
if( ((o = getObject( node, OWL.complementOf.asNode() )) != null) ) {
log.info( "Blank nodes in class variable positions are not supported" );
// TODO
}
aTerm = ATermUtils.makeBnode( node.getBlankNodeId().toString() );
}
}
else {
String uri = node.getURI();
aTerm = ATermUtils.makeTermAppl( uri );
}
terms.put( node, aTerm );
}
/*
* Given a parameterized query, resolve the node (SPO of a triple pattern)
* i.e. if it is a variable and the variable name is contained in the
* initial binding (as a parameter) resolve it, i.e. substitute the variable
* with the constant.
*/
private List resolveParameterization(List> triples) {
if( triples == null )
throw new NullPointerException( "The set of triples cannot be null" );
// Ensure that the initial binding is not a null pointer
if( initialBinding == null )
initialBinding = new QuerySolutionMap();
List ret = new ArrayList();
for( final Triple t : triples.toArray( new Triple[triples.size()] ) ) {
if( !triples.contains( t ) ) {
continue;
}
Node s = resolveParameterization( t.getSubject() );
Node p = resolveParameterization( t.getPredicate() );
Node o = resolveParameterization( t.getObject() );
ret.add( Triple.create( s, p, o ) );
}
return ret;
}
private Node resolveParameterization(Node node) {
if( node == null )
throw new NullPointerException( "Node is null" );
if( initialBinding == null )
throw new NullPointerException( "Initial binding is null" );
if( node.isConcrete() )
return node;
RDFNode binding = initialBinding.get( node.getName() );
if( binding == null )
return node;
return binding.asNode();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy