Skip to content

Commit

Permalink
Merge pull request #293 from LiUSemWeb/ExtendImplementationOfApplying…
Browse files Browse the repository at this point in the history
…VocabularyMappings

Extend the implementation of 'ApplyVocabularyMappings'
  • Loading branch information
hartig authored May 3, 2023
2 parents 4217005 + 875a9d1 commit 35a0444
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.jena.vocabulary.RDF;
import se.liu.ida.hefquin.engine.data.VocabularyMapping;
import se.liu.ida.hefquin.engine.data.mappings.VocabularyMappingUtils;
import se.liu.ida.hefquin.engine.federation.FederationMember;
import se.liu.ida.hefquin.engine.federation.SPARQLEndpoint;
Expand All @@ -29,36 +32,15 @@
import se.liu.ida.hefquin.engine.queryplan.logical.impl.LogicalPlanWithNaryRootImpl;
import se.liu.ida.hefquin.engine.queryplan.logical.impl.LogicalPlanWithNullaryRootImpl;
import se.liu.ida.hefquin.engine.queryplan.logical.impl.LogicalPlanWithUnaryRootImpl;
import se.liu.ida.hefquin.engine.queryplan.utils.LogicalOpUtils;

public class ApplyVocabularyMappings implements HeuristicForLogicalOptimization {
protected final boolean compressVocabularyRewriting;

/**
* Rewrites the given logical plan with a request operator as root into
* a logical plan that uses the local vocabulary of the federation member of
* the request.
*/
public static LogicalPlan rewriteToUseLocalVocabulary( final LogicalPlan inputPlan ) {
if(!(inputPlan.getRootOperator() instanceof LogicalOpRequest)) {
throw new IllegalArgumentException( "Input plan does not have a request operator as root: " + inputPlan.getRootOperator().getClass().getName() );
}
final LogicalOpRequest<?, ?> reqOp = (LogicalOpRequest<?, ?>) inputPlan.getRootOperator();
final FederationMember fm = reqOp.getFederationMember();
if (fm.getVocabularyMapping() == null) { // If no vocabulary mapping, nothing to translate.
return inputPlan;
}

if(!(reqOp.getRequest() instanceof SPARQLRequest)) {
throw new IllegalArgumentException( "Request must be a SPARQLRequest: " + reqOp.getRequest().getClass().getName() );
}

final SPARQLRequest req = (SPARQLRequest) reqOp.getRequest();
final SPARQLGraphPattern p = req.getQueryPattern();

final SPARQLGraphPattern newP = VocabularyMappingUtils.translateGraphPattern(p, fm.getVocabularyMapping());
return ( newP.equals(p) ) ? inputPlan : rewriteReqOf(newP, fm);
ApplyVocabularyMappings( final boolean compressVocabularyRewriting ){
this.compressVocabularyRewriting = compressVocabularyRewriting;
}


/**
* Rewrites an initial logical plan into a second plan which incorporates translations of local to global vocabulary and request-operator rewriting.
* This method implements the rewriteLogPlan pseudocode of Helgesson's B.Sc thesis.
Expand All @@ -67,14 +49,25 @@ public static LogicalPlan rewriteToUseLocalVocabulary( final LogicalPlan inputPl
public LogicalPlan apply( final LogicalPlan inputPlan ) {
if (inputPlan.getRootOperator() instanceof LogicalOpRequest) {
final LogicalOpRequest<?,?> requestOp = (LogicalOpRequest<?,?>) inputPlan.getRootOperator();
if(requestOp.getFederationMember().getVocabularyMapping() != null) { // If fm has a vocabulary mapping vm
final LogicalOpLocalToGlobal l2g = new LogicalOpLocalToGlobal(requestOp.getFederationMember().getVocabularyMapping());
final LogicalPlan rw = rewriteToUseLocalVocabulary(inputPlan);
return new LogicalPlanWithUnaryRootImpl(l2g,rw);
} else {

final VocabularyMapping vm = requestOp.getFederationMember().getVocabularyMapping();
if ( vm != null) { // If fm has a vocabulary mapping vm
final LogicalPlan newInputPlan = rewriteToUseLocalVocabulary(inputPlan);

// For a compressed version of query plan, check if it is necessary to add the l2g operator over a request based on the form of the graph pattern.
if ( !compressVocabularyRewriting || checkIfLocalToGlobalNeeded(requestOp) ) {
final LogicalOpLocalToGlobal l2g = new LogicalOpLocalToGlobal(vm);
return new LogicalPlanWithUnaryRootImpl(l2g, newInputPlan);
}
else {
return newInputPlan;
}
}
else {
return inputPlan;
}
} else if ((inputPlan.getRootOperator() instanceof LogicalOpMultiwayJoin) || (inputPlan.getRootOperator() instanceof LogicalOpMultiwayUnion)) {
}
else if ((inputPlan.getRootOperator() instanceof LogicalOpMultiwayJoin) || (inputPlan.getRootOperator() instanceof LogicalOpMultiwayUnion)) {
final List<LogicalPlan> rewrittenSubplans = new ArrayList<>();
final Iterator<LogicalPlan> it = ((LogicalPlanWithNaryRoot) inputPlan).getSubPlans();
boolean rewritten = false;
Expand All @@ -101,6 +94,31 @@ public LogicalPlan apply( final LogicalPlan inputPlan ) {
}
}

/**
* Rewrites the given logical plan with a request operator as root into
* a logical plan that uses the local vocabulary of the federation member of
* the request.
*/
public static LogicalPlan rewriteToUseLocalVocabulary( final LogicalPlan inputPlan ) {
if(!(inputPlan.getRootOperator() instanceof LogicalOpRequest)) {
throw new IllegalArgumentException( "Input plan does not have a request operator as root: " + inputPlan.getRootOperator().getClass().getName() );
}
final LogicalOpRequest<?, ?> reqOp = (LogicalOpRequest<?, ?>) inputPlan.getRootOperator();
final FederationMember fm = reqOp.getFederationMember();
if (fm.getVocabularyMapping() == null) { // If no vocabulary mapping, nothing to translate.
return inputPlan;
}

if(!(reqOp.getRequest() instanceof SPARQLRequest)) {
throw new IllegalArgumentException( "Request must be a SPARQLRequest: " + reqOp.getRequest().getClass().getName() );
}

final SPARQLRequest req = (SPARQLRequest) reqOp.getRequest();
final SPARQLGraphPattern p = req.getQueryPattern();

final SPARQLGraphPattern newP = VocabularyMappingUtils.translateGraphPattern(p, fm.getVocabularyMapping());
return ( newP.equals(p) ) ? inputPlan : rewriteReqOf(newP, fm);
}

/**
* Creates a logical plan where all requests are TriplePatternRequests
Expand Down Expand Up @@ -173,4 +191,28 @@ else if( pattern instanceof SPARQLGroupPattern ) {
}
}

/**
* This function is used to check if it is necessary to add a l2g operator over a request based on the form of the graph pattern.
* The current implementation assumes that only concepts and roles are being considered in vocabulary mapping
* and that the data of the federation members is only instance data (i.e., properties
* appear only in the predicate position of triples and classes appear only in the
* object position of rdf:type triples).
*/
protected boolean checkIfLocalToGlobalNeeded( final LogicalOpRequest<?,?> requestOp ){
final Set<TriplePattern> tps = LogicalOpUtils.getTriplePatternsOfReq(requestOp);
for ( final TriplePattern tp : tps ) {
// If any triple pattern is in the form of (-, ?p, -) or (-, rdf:type, ?o),
// the intermediate results might need to be rewritten, which
// requires adding a L2G operator over the request.
if ( tp.asJenaTriple().getPredicate().isVariable() ) {
return true;
}
if ( tp.asJenaTriple().getPredicate().equals(RDF.Nodes.type)
&& tp.asJenaTriple().getObject().isVariable() ) {
return true;
}
}
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public LogicalOptimizerImpl() {
//// vocabulary mappings is only supported by the naive algorithm
//// currently since the cost model needs to be extended to consider
//// operators PhysicalOpLocalToGlobal and PhysicalOpGlobalToLocal.
//heuristics.add( new ApplyVocabularyMappings());
// heuristics.add( new ApplyVocabularyMappings(false) );
}

@Override
Expand Down

0 comments on commit 35a0444

Please sign in to comment.