All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.clarkparsia.pellet.sparqldl.model.QueryImpl 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.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;

import org.mindswap.pellet.KnowledgeBase;
import org.mindswap.pellet.exceptions.InternalReasonerException;
import org.mindswap.pellet.utils.ATermUtils;

import aterm.ATermAppl;
import aterm.ATermList;

import com.clarkparsia.pellet.utils.TermFactory;

/**
 * 

* Title: Default implementation of the {@link Query} *

*

* Description: *

*

* Copyright: Copyright (c) 2007 *

*

* Company: Clark & Parsia, LLC. *

* * @author Petr Kremen */ public class QueryImpl implements Query { private static final ATermAppl DEFAULT_NAME = TermFactory.term( "query" ); // COMMON PART private ATermAppl name = DEFAULT_NAME; private List allAtoms; private KnowledgeBase kb; private List resultVars; private Set allVars; private Set individualsAndLiterals; private boolean ground; private boolean distinct; private Filter filter; private QueryParameters parameters; // VARIABLES private EnumMap> distVars; public QueryImpl(final KnowledgeBase kb, final boolean distinct) { this.kb = kb; this.ground = true; this.allAtoms = new ArrayList(); this.resultVars = new ArrayList(); this.allVars = new HashSet(); this.individualsAndLiterals = new HashSet(); this.distVars = new EnumMap>( VarType.class ); for( final VarType type : VarType.values() ) { distVars.put( type, new HashSet() ); } this.distinct = distinct; } public QueryImpl(final Query query) { this( query.getKB(), query.isDistinct() ); this.name = query.getName(); this.parameters = query.getQueryParameters(); } /** * {@inheritDoc} */ public void add(final QueryAtom atom) { if( allAtoms.contains( atom ) ) { return; } allAtoms.add( atom ); for( final ATermAppl a : atom.getArguments() ) { if( ATermUtils.isVar( a ) ) { if( !allVars.contains( a ) ) { allVars.add( a ); } } else if( ATermUtils.isLiteral( a ) || kb.isIndividual( a ) ) { if( !individualsAndLiterals.contains( a ) ) { individualsAndLiterals.add( a ); } } } ground = ground && atom.isGround(); } /** * {@inheritDoc} */ public Set getDistVarsForType(final VarType type) { return distVars.get( type ); } /** * {@inheritDoc} */ public void addDistVar(ATermAppl a, final VarType type) { Set set = distVars.get( type ); if( !set.contains( a ) ) { set.add( a ); } } /** * {@inheritDoc} */ public void addResultVar(ATermAppl a) { resultVars.add( a ); } /** * {@inheritDoc} */ public List getAtoms() { return Collections.unmodifiableList( allAtoms ); } /** * {@inheritDoc} */ public Set getConstants() { return Collections.unmodifiableSet( individualsAndLiterals ); } /** * {@inheritDoc} */ public Set getDistVars() { final Set result = new HashSet(); for( final VarType t : VarType.values() ) { result.addAll( distVars.get( t ) ); } return result; } /** * {@inheritDoc} */ public Set getUndistVars() { final Set result = new HashSet( allVars ); result.removeAll( getDistVars() ); return result; } /** * {@inheritDoc} */ public List getResultVars() { return Collections.unmodifiableList( resultVars ); } /** * {@inheritDoc} */ public Set getVars() { return Collections.unmodifiableSet( allVars ); } /** * {@inheritDoc} */ public boolean isGround() { return ground; } /** * {@inheritDoc} */ public KnowledgeBase getKB() { return kb; } /** * {@inheritDoc} */ public void setKB(KnowledgeBase kb) { this.kb = kb; } /** * {@inheritDoc} */ public Query apply(final ResultBinding binding) { final List atoms = new ArrayList(); for( final QueryAtom atom : getAtoms() ) { atoms.add( atom.apply( binding ) ); } final QueryImpl query = new QueryImpl( this ); query.resultVars.addAll( this.resultVars ); query.resultVars.removeAll( binding.getAllVariables() ); for( final VarType type : VarType.values() ) { for( final ATermAppl atom : getDistVarsForType( type ) ) { if( !binding.isBound( atom ) ) { query.addDistVar( atom, type ); } } } for( final QueryAtom atom : atoms ) { query.add( atom ); } return query; } /** * {@inheritDoc} TODO */ public ATermAppl rollUpTo(final ATermAppl var, final Collection stopList, final boolean stopOnConstants) { if( getDistVarsForType( VarType.LITERAL ).contains( var ) && !getDistVarsForType( VarType.INDIVIDUAL ).contains( var ) && !individualsAndLiterals.contains( var ) ) { throw new InternalReasonerException( "Trying to roll up to the variable '" + var + "' which is not distinguished and individual." ); } ATermList classParts = ATermUtils.EMPTY_LIST; final Set visited = new HashSet(); if( stopOnConstants ) { visited.addAll( getConstants() ); } final Collection inEdges = findAtoms( QueryPredicate.PropertyValue, null, null, var ); for( final QueryAtom a : inEdges ) { classParts = classParts.append( rollEdgeIn( QueryPredicate.PropertyValue, a, visited, stopList ) ); } final Collection outEdges = findAtoms( QueryPredicate.PropertyValue, var, null, null ); for( final QueryAtom a : outEdges ) { classParts = classParts.append( rollEdgeOut( QueryPredicate.PropertyValue, a, visited, stopList ) ); } classParts = classParts.concat( getClasses( var ) ); return ATermUtils.makeAnd( classParts ); } // TODO optimize - cache private ATermList getClasses(final ATermAppl a) { final List aterms = new ArrayList(); for( final QueryAtom atom : findAtoms( QueryPredicate.Type, a, null ) ) { final ATermAppl arg = atom.getArguments().get( 1 ); if( ATermUtils.isVar( arg ) ) { throw new InternalReasonerException( "Variables as predicates are not supported yet" ); } aterms.add( arg ); } if( !ATermUtils.isVar( a ) ) { aterms.add( ATermUtils.makeValue( a ) ); } return ATermUtils.makeList( aterms ); } /** * TODO */ private ATermAppl rollEdgeOut(final QueryPredicate allowed, final QueryAtom atom, final Set visited, final Collection stopList) { switch ( atom.getPredicate() ) { case PropertyValue: final ATermAppl subj = atom.getArguments().get( 0 ); final ATermAppl pred = atom.getArguments().get( 1 ); final ATermAppl obj = atom.getArguments().get( 2 ); if( ATermUtils.isVar( pred ) ) { // variables as predicates are not supported yet. return ATermUtils.TOP; } visited.add( subj ); if( visited.contains( obj ) ) { ATermList temp = getClasses( obj ); if( temp.getLength() == 0 ) { if( kb.isDatatypeProperty( pred ) ) // return ATermUtils.makeSoMin(pred, 1, // ATermUtils.TOP_LIT); return ATermUtils.makeSomeValues( pred, ATermUtils.TOP_LIT ); else return ATermUtils.makeSomeValues( pred, ATermUtils.TOP ); } else { return ATermUtils.makeSomeValues( pred, ATermUtils.makeAnd( temp ) ); } } if( ATermUtils.isLiteral( obj ) ) { ATermAppl type = ATermUtils.makeValue( obj ); return ATermUtils.makeSomeValues( pred, type ); } // TODO // else if (litVars.contains(obj)) { // Datatype dtype = getDatatype(obj); // // return ATermUtils.makeSomeValues(pred, dtype.getName()); // } ATermList targetClasses = getClasses( obj ); for( final QueryAtom in : _findAtoms( stopList, allowed, null, null, obj ) ) { if( !in.equals( atom ) ) { targetClasses = targetClasses.append( rollEdgeIn( allowed, in, visited, stopList ) ); } } final List targetOuts = _findAtoms( stopList, allowed, obj, null, null ); if( targetClasses.isEmpty() ) { if( targetOuts.size() == 0 ) { // this is a simple leaf node if( kb.isDatatypeProperty( pred ) ) return ATermUtils.makeSomeValues( pred, ATermUtils.TOP_LIT ); else return ATermUtils.makeSomeValues( pred, ATermUtils.TOP ); } else { // not a leaf node, recurse over all outgoing edges ATermList outs = ATermUtils.EMPTY_LIST; for( final QueryAtom currEdge : targetOuts ) { outs = outs.append( rollEdgeOut( allowed, currEdge, visited, stopList ) ); } return ATermUtils.makeSomeValues( pred, ATermUtils.makeAnd( outs ) ); } } else { if( targetOuts.size() == 0 ) { // this is a simple leaf node, but with classes specified return ATermUtils.makeSomeValues( pred, ATermUtils.makeAnd( targetClasses ) ); } else { // not a leaf node, recurse over all outgoing edges ATermList outs = ATermUtils.EMPTY_LIST; for( final QueryAtom currEdge : targetOuts ) { outs = outs.append( rollEdgeOut( allowed, currEdge, visited, stopList ) ); } for( int i = 0; i < targetClasses.getLength(); i++ ) { outs = outs.append( targetClasses.elementAt( i ) ); } return ATermUtils.makeSomeValues( pred, ATermUtils.makeAnd( outs ) ); } } default: throw new RuntimeException( "This atom cannot be included to rolling-up : " + atom ); } } // TODO this should die if called on a literal node private ATermAppl rollEdgeIn(final QueryPredicate allowed, final QueryAtom atom, final Set visited, final Collection stopList) { switch ( atom.getPredicate() ) { case PropertyValue: final ATermAppl subj = atom.getArguments().get( 0 ); final ATermAppl pred = atom.getArguments().get( 1 ); final ATermAppl obj = atom.getArguments().get( 2 ); ATermAppl invPred = kb.getRBox().getRole( pred ).getInverse().getName(); if( ATermUtils.isVar( pred ) ) { throw new InternalReasonerException( "Variables as predicates are not supported yet" ); // // TODO variables as predicates are not supported yet. // return ATermUtils.TOP; } visited.add( obj ); if( visited.contains( subj ) ) { ATermList temp = getClasses( subj ); if( temp.getLength() == 0 ) { if( kb.isDatatypeProperty( invPred ) ) return ATermUtils.makeSomeValues( invPred, ATermUtils.TOP_LIT ); else return ATermUtils.makeSomeValues( invPred, ATermUtils.TOP ); } else { return ATermUtils.makeSomeValues( invPred, ATermUtils.makeAnd( temp ) ); } } ATermList targetClasses = getClasses( subj ); final List targetIns = _findAtoms( stopList, allowed, null, null, subj ); for( final QueryAtom o : _findAtoms( stopList, allowed, subj, null, null ) ) { if( !o.equals( atom ) ) { targetClasses = targetClasses.append( rollEdgeOut( allowed, o, visited, stopList ) ); } } if( targetClasses.isEmpty() ) { if( targetIns.isEmpty() ) { // this is a simple leaf node if( kb.isDatatypeProperty( pred ) ) return ATermUtils.makeSomeValues( invPred, ATermUtils.TOP_LIT ); else return ATermUtils.makeSomeValues( invPred, ATermUtils.TOP ); } else { // not a leaf node, recurse over all incoming edges ATermList ins = ATermUtils.EMPTY_LIST; for( QueryAtom currEdge : targetIns ) { ins = ins.append( rollEdgeIn( allowed, currEdge, visited, stopList ) ); } return ATermUtils.makeSomeValues( invPred, ATermUtils.makeAnd( ins ) ); } } else { if( targetIns.isEmpty() ) { // this is a simple leaf node, but with classes specified return ATermUtils.makeSomeValues( invPred, ATermUtils.makeAnd( targetClasses ) ); } else { // not a leaf node, recurse over all outgoing edges ATermList ins = ATermUtils.EMPTY_LIST; for( QueryAtom currEdge : targetIns ) { ins = ins.append( rollEdgeIn( allowed, currEdge, visited, stopList ) ); } for( int i = 0; i < targetClasses.getLength(); i++ ) { ins = ins.append( targetClasses.elementAt( i ) ); } return ATermUtils.makeSomeValues( invPred, ATermUtils.makeAnd( ins ) ); } } default: throw new RuntimeException( "This atom cannot be included to rolling-up : " + atom ); } } private List _findAtoms(final Collection stopList, final QueryPredicate predicate, final ATermAppl... args) { final List list = new ArrayList(); for( final QueryAtom atom : allAtoms ) { if( predicate.equals( atom.getPredicate() ) ) { int i = 0; boolean add = true; for( final ATermAppl arg : atom.getArguments() ) { final ATermAppl argValue = args[i++]; if( (argValue != null && argValue != arg) || stopList.contains( arg ) ) { add = false; break; } } if( add ) { list.add( atom ); } } } return list; } /** * {@inheritDoc} */ public List findAtoms(final QueryPredicate predicate, final ATermAppl... args) { return _findAtoms( Collections.emptySet(), predicate, args ); } /** * {@inheritDoc} */ public Query reorder(int[] ordering) { if( ordering.length != allAtoms.size() ) { throw new InternalReasonerException( "Ordering permutation must be of the same size as the query : " + ordering.length ); } final QueryImpl newQuery = new QueryImpl( this ); // shallow copies for faster processing for( int j = 0; j < ordering.length; j++ ) { newQuery.allAtoms.add( allAtoms.get( ordering[j] ) ); } newQuery.allVars = allVars; newQuery.distVars = distVars; newQuery.individualsAndLiterals = individualsAndLiterals; newQuery.resultVars = resultVars; newQuery.ground = ground; return newQuery; } /** * {@inheritDoc} */ public void remove(QueryAtom atom) { if( !allAtoms.contains( atom ) ) { return; } allAtoms.remove( atom ); final Set rest = new HashSet(); boolean ground = true; for( final QueryAtom atom2 : allAtoms ) { ground &= atom2.isGround(); rest.addAll( atom2.getArguments() ); } this.ground = ground; final Set toRemove = new HashSet( atom.getArguments() ); toRemove.removeAll( rest ); for( final ATermAppl a : toRemove ) { allVars.remove( a ); for (Entry> entry : distVars.entrySet() ) { entry.getValue().remove( a ); } resultVars.remove( a ); individualsAndLiterals.remove( a ); } } @Override public String toString() { return toString( false ); } public String toString(boolean multiLine) { final String indent = multiLine ? " " : " "; final StringBuffer sb = new StringBuffer(); sb.append( ATermUtils.toString( name ) + "(" ); for( int i = 0; i < resultVars.size(); i++ ) { ATermAppl var = resultVars.get( i ); if( i > 0 ) sb.append( ", " ); sb.append( ATermUtils.toString( var ) ); } sb.append( ")" ); if( allAtoms.size() > 0 ) { sb.append( " :-" ); if( multiLine ) sb.append( "\n" ); for( int i = 0; i < allAtoms.size(); i++ ) { final QueryAtom a = allAtoms.get( i ); if( i > 0 ) { sb.append( "," ); if( multiLine ) sb.append( "\n" ); } sb.append( indent ); sb.append( a.toString() ); // TODO qNameProvider } } sb.append( "." ); if( multiLine ) sb.append( "\n" ); return sb.toString(); } /** * {@inheritDoc} */ public boolean isDistinct() { return distinct; } /** * {@inheritDoc} */ public Filter getFilter() { return filter; } /** * {@inheritDoc} */ public void setFilter(Filter filter) { this.filter = filter; } public void setQueryParameters(QueryParameters parameters) { this.parameters = parameters; } public QueryParameters getQueryParameters() { return parameters; } public ATermAppl getName() { return name; } public void setName(ATermAppl name) { this.name = name; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy