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

io.github.sparqlanything.engine.FacadeXOpExecutor Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
/*
 * Copyright (c) 2023 SPARQL Anything Contributors @ http://github.com/sparql-anything
 *
 * 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 io.github.sparqlanything.engine;

import io.github.sparqlanything.model.TriplifierHTTPException;
import org.apache.jena.graph.Triple;
import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.algebra.op.OpBGP;
import org.apache.jena.sparql.algebra.op.OpPropFunc;
import org.apache.jena.sparql.algebra.op.OpService;
import org.apache.jena.sparql.algebra.optimize.TransformPropertyFunction;
import org.apache.jena.sparql.engine.ExecutionContext;
import org.apache.jena.sparql.engine.QueryIterator;
import org.apache.jena.sparql.engine.iterator.QueryIterAssign;
import org.apache.jena.sparql.engine.join.Join;
import org.apache.jena.sparql.engine.main.OpExecutor;
import org.apache.jena.sparql.engine.main.QC;
import org.apache.jena.sparql.util.Symbol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

public class FacadeXOpExecutor extends OpExecutor {

	public final static Symbol strategy = Symbol.create("facade-x-strategy");
	private static final Logger logger = LoggerFactory.getLogger(FacadeXOpExecutor.class);
	private final FXWorkerOpService fxWorkerService;
	private final FXWorkerOpBGP fxWorkerOpBGP;

	private final FXWorkerOpPropFunc fxWorkerOpPropFunc ;

	public FacadeXOpExecutor(ExecutionContext execCxt) {
		super(execCxt);
		TriplifierRegister triplifierRegister = TriplifierRegister.getInstance();
		DatasetGraphCreator dgc = new DatasetGraphCreator(execCxt);
		fxWorkerService = new FXWorkerOpService(triplifierRegister, dgc);
		fxWorkerOpBGP = new FXWorkerOpBGP(triplifierRegister, dgc);
		fxWorkerOpPropFunc = new FXWorkerOpPropFunc(triplifierRegister, dgc);
	}

	protected QueryIterator execute(final OpPropFunc opPropFunc, QueryIterator input){
		logger.trace("OpProp  {}", opPropFunc);
		if(!Utils.isFacadeXMagicPropertyNode(opPropFunc.getProperty())||this.execCxt.getClass() == FacadeXExecutionContext.class){
			return super.execute(opPropFunc, input);
		}else {
			try {
				return fxWorkerOpPropFunc.execute(opPropFunc, input, this.execCxt);
			} catch (ClassNotFoundException | InvocationTargetException | InstantiationException |
					 IllegalAccessException | NoSuchMethodException | IOException | UnboundVariableException |
					 TriplifierHTTPException e) {
				throw new RuntimeException(e);
			}
		}
	}

	protected QueryIterator execute(final OpBGP opBGP, QueryIterator input) {
		logger.trace("Execute OpBGP {}", opBGP.getPattern().toString());



		if(hasFXSymbols(this.execCxt) && !this.execCxt.getContext().isDefined(FacadeXExecutionContext.hasServiceClause)){
			try {
				return fxWorkerOpBGP.execute(opBGP, input, this.execCxt);
			} catch (IOException | InstantiationException | IllegalAccessException | InvocationTargetException |
					 NoSuchMethodException | ClassNotFoundException | UnboundVariableException |
					 TriplifierHTTPException e) {
				throw new RuntimeException(e);
			}
		}

		// check that the BGP is within a FacadeX-SERVICE clause
		if (this.execCxt.getClass() == FacadeXExecutionContext.class) {
			// check that the BGP contains FacadeX Magic properties
			logger.trace("FacadeX Execution context");
			List magicPropertyTriples = Utils.getFacadeXMagicPropertyTriples(opBGP.getPattern());
			if (!magicPropertyTriples.isEmpty()) {
				logger.trace("BGP has magic properties");
				return super.execute(Utils.excludeMagicPropertyTriples(Utils.excludeFXProperties(opBGP)), executeMagicProperties(input, magicPropertyTriples, this.execCxt));
			} else {
				// execute BGP by excluding FX properties
				logger.trace("Execute BGP by excluding FX properties");
				//return QC.execute(Utils.excludeFXProperties(opBGP), input, new ExecutionContext(this.execCxt.getDataset()));
				return QC.execute(Utils.excludeFXProperties(opBGP), input, new ExecutionContext(execCxt));
			}
		}

		Op opTransformed =  TransformPropertyFunction.transform(opBGP, this.execCxt.getContext());
		if(!opTransformed.equals(opBGP)){
			return super.executeOp(opTransformed, input);
		}
		logger.trace("Execute with default Jena execution");


		// go with the default Jena execution
		return super.execute(opBGP, input);
	}

	private boolean hasFXSymbols(ExecutionContext execCxt) {
		for(Symbol s : execCxt.getContext().keys()){
			if(s.getClass() == FXSymbol.class){
				return true;
			}
		}
		return false;
	}

	protected QueryIterator execute(final OpService opService, QueryIterator input) {
		logger.trace("Execute opService {}", opService.toString());
		// check if service iri is a variable, in case postpone the execution
		if (opService.getService().isVariable()) return Utils.postpone(opService, input, execCxt);

		// check if the service is a FacadeXURI
		if (opService.getService().isURI() && Utils.isFacadeXURI(opService.getService().getURI())) {
			try {
				// go with the FacadeX default execution
//				return executeDefaultFacadeX(opService, input);
				return fxWorkerService.execute(opService, input, execCxt);
			} catch (IllegalArgumentException | SecurityException | IOException | InstantiationException |
					 IllegalAccessException | InvocationTargetException | NoSuchMethodException |
					 ClassNotFoundException | TriplifierHTTPException e) {
				logger.error("An error occurred: {}", e.getMessage());
				throw new RuntimeException(e);
			} catch (UnboundVariableException e) {
				// manage the case of properties are passed via BGP and there are variables in it
				return catchUnboundVariableException(opService, e.getOpBGP(), input, e);
			}
		}

		// go with the default Jena execution
		return super.execute(opService, input);
	}

	private QueryIterator catchUnboundVariableException(Op op, OpBGP opBGP, QueryIterator input, UnboundVariableException e) {
		// Proceed with the next operation
		OpBGP fakeBGP = Utils.extractFakePattern(opBGP);
		if (e.getOpTable() != null) {
			logger.trace("Executing table");
			QueryIterator qIterT = e.getOpTable().getTable().iterator(execCxt);
			QueryIterator qIter = Join.join(input, qIterT, execCxt);
			return Utils.postpone(op, qIter, execCxt);
		} else if (e.getOpExtend() != null) {
			logger.trace("Executing op extend");
			QueryIterator qIter = exec(e.getOpExtend().getSubOp(), input);
			qIter = new QueryIterAssign(qIter, e.getOpExtend().getVarExprList(), execCxt, true);
			return Utils.postpone(op, qIter, execCxt);
		}
		logger.trace("Executing fake pattern {}", fakeBGP);
		return Utils.postpone(op, QC.execute(fakeBGP, input, execCxt), execCxt);
	}

	private QueryIterator executeMagicProperties(QueryIterator input, List propFuncTriples, ExecutionContext execCxt) {
		QueryIterator input2 = input;
		for (Triple t : propFuncTriples) {
			input2 = QC.execute(Utils.getOpPropFuncAnySlot(t), input2, execCxt);
		}
		return input2;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy