
fr.boreal.component_builder.ComponentBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of integraal-component Show documentation
Show all versions of integraal-component Show documentation
Components for the main functionalities of InteGraal
package fr.boreal.component_builder;
import java.sql.SQLException;
import java.time.Duration;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.boreal.backward_chaining.evaluators.QueryRewriter;
import fr.boreal.component_builder.api.IComponentBuilder;
import fr.boreal.component_builder.api.IOperationResult;
import fr.boreal.component_builder.api.algorithm.IAlgorithmParameters;
import fr.boreal.component_builder.api.scenario.IInputDataScenario;
import fr.boreal.component_builder.components.ChaseComponentBuilder;
import fr.boreal.component_builder.components.FactBaseLoaderFromFile;
import fr.boreal.component_builder.components.QueryAnsweringComponentBuilder;
import fr.boreal.component_builder.components.RewritingComponentBuilder;
import fr.boreal.component_builder.operations.FactBaseLoadingOperationResult;
import fr.boreal.component_builder.operations.OperationNotPerformed;
import fr.boreal.component_builder.operations.QueryBaseLoadingOperationResult;
import fr.boreal.component_builder.operations.RuleBaseLoadingOperationResult;
import fr.boreal.component_builder.operations.RuleCompilationOperationResult;
import fr.boreal.forward_chaining.chase.Chase;
import fr.boreal.io.dlgp.DlgpParser;
import fr.boreal.model.component.InteGraalKeywords;
import fr.boreal.model.component.InteGraalKeywords.Algorithms;
import fr.boreal.model.kb.api.FactBase;
import fr.boreal.model.kb.api.RuleBase;
import fr.boreal.model.kb.impl.RuleBaseImpl;
import fr.boreal.model.query.api.Query;
import fr.boreal.model.rule.api.FORule;
import fr.boreal.model.ruleCompilation.HierarchicalRuleCompilation;
import fr.boreal.model.ruleCompilation.NoRuleCompilation;
import fr.boreal.model.ruleCompilation.api.RuleCompilation;
import fr.boreal.model.ruleCompilation.api.RuleCompilationResult;
import fr.boreal.model.ruleCompilation.id.IDRuleCompilation;
import fr.boreal.query_evaluation.component.CountingQueryEvaluator;
import fr.boreal.query_evaluation.component.QueryEvaluationInput;
import fr.boreal.query_evaluation.component.QueryEvaluationOutput;
import fr.boreal.query_evaluation.component.QueryEvaluator;
import fr.boreal.storage.external.rdbms.RDBMSStore;
import fr.lirmm.boreal.util.evaluator.MultiEvaluator;
import fr.lirmm.boreal.util.externalHaltingConditions.ExternalAlgorithmHaltingConditions;
/**
*
* A component builder is able to return an InteGraal object performing a main
* task, such as chasing, rewriting, evaluating queries, compiling rules.
*
*/
public class ComponentBuilder implements IComponentBuilder {
private static final Logger LOG = LoggerFactory.getLogger(ComponentBuilder.class);
private final IInputDataScenario kbscenario;
private final IAlgorithmParameters integraalAlgorithmParameters;
private Optional factbase;
private Optional> ruleset;
private Optional> querybase;
private Optional> queryEvaluator;
private Optional chaseAlgorithm;
private Optional rewriter;
private Optional compilResult;
private RuleCompilation compilation; // assumed to be always set
///////////////////////////////
///////////////////////////////
///////////////////////////////
///////////////////////////////
/// CONSTURCTOR
///////////////////////////////
///////////////////////////////
///////////////////////////////
///////////////////////////////
/**
* Constructs a component builder from the specified input scenario and
* algorithm parameters.
*
* @param inputScenario the knowledge base scenario, not null.
* @param algorithmParameters the algorithm parameters for the InteGraal
* component, not null. base files specified by the
* by the kbscenario.
*/
public ComponentBuilder(IInputDataScenario inputScenario, IAlgorithmParameters algorithmParameters) {
this.kbscenario = inputScenario;
this.integraalAlgorithmParameters = algorithmParameters;
this.factbase = Optional.empty();
this.querybase = Optional.empty();
this.ruleset = Optional.empty();
this.compilResult = Optional.empty();
this.queryEvaluator = Optional.empty();
this.chaseAlgorithm = Optional.empty();
this.rewriter = Optional.empty();
}
///////////////////////////////
///////////////////////////////
///////////////////////////////
///////////////////////////////
/// PUBLIC METHODS
///////////////////////////////
///////////////////////////////
///////////////////////////////
///////////////////////////////
/**
*
* Returns the factbase object used by the builder.
*
*/
public FactBase getFactbase() {
checkExists(factbase);
return factbase.get();
}
/**
*
* Returns a new rulebase containing all rules used by the builder.
*
*/
public RuleBase getRulebase() {
checkExists(ruleset);
return new RuleBaseImpl(ruleset.get());
}
/**
*
* Returns the query set object used by the builder.
*
*/
public Collection getQueries() {
checkExists(querybase);
return querybase.get();
}
/**
*
* Returns the rule compilation result used by the builder.
*
*/
public RuleCompilationResult getRuleCompilationResult() {
checkExists(compilResult);
return compilResult.get();
}
/**
* Returns chase algorithm based on the provided configuration.
*
* @return the prepared instance of the Chase algorithm.
*/
public Chase buildOrGetChase() {
checkSaturationService();
if (chaseAlgorithm.isPresent()) {
return chaseAlgorithm.get();
}
checkNecessaryElementsForComponent(List.of(factbase, ruleset),
InteGraalKeywords.Algorithms.KB_CHASE);
Chase customizedChase = ChaseComponentBuilder.prepareAndGetChaseFrom(getFactbase(), getRulebase(),
integraalAlgorithmParameters);
this.chaseAlgorithm = Optional.ofNullable(customizedChase);
return customizedChase;
}
/**
*
* @return a rewriting algorithm based on the current configuration
*/
public QueryRewriter buildOrGetRewriter() {
checkRewritingService();
if (rewriter.isPresent()) {
return rewriter.get();
}
checkNecessaryElementsForComponent(List.of(querybase, ruleset),
InteGraalKeywords.Algorithms.OMQ_REWRITING);
QueryRewriter customizedRewriter = RewritingComponentBuilder.prepareAndGetRewriterFrom(getQueries(),
getRulebase(), getCompilation(), getExternalHaltingConditions());
this.rewriter = Optional.of(customizedRewriter);
return customizedRewriter;
}
private ExternalAlgorithmHaltingConditions getExternalHaltingConditions() {
return this.integraalAlgorithmParameters.getExternalHaltingConditions();
}
private RuleCompilation getCompilation() {
return this.compilation;
}
/**
*
*
* @return a query evaluator based on the current configuration
*/
public QueryEvaluator buildOrGetQueryAnsweringAlgorithm() {
checkQueryAnsweringService();
if (queryEvaluator.isPresent()) {
return (QueryEvaluator) queryEvaluator.get();
}
checkNecessaryElementsForComponent(List.of(querybase, factbase),
InteGraalKeywords.Algorithms.OMQ_REWRITING);
QueryEvaluator customizedEvaluator = QueryAnsweringComponentBuilder
.prepareAndGetQueryAnsweringFrom(getQueries(), getFactbase(), getExternalHaltingConditions());
this.queryEvaluator = Optional.of(customizedEvaluator);
return customizedEvaluator;
}
/**
*
*
* @return a query evaluator based on the current configuration
*/
public CountingQueryEvaluator buildOrGetCountingQueryAnsweringAlgorithm() {
checkQueryAnsweringService();
if (queryEvaluator.isPresent()) {
return (CountingQueryEvaluator) queryEvaluator.get();
}
checkNecessaryElementsForComponent(List.of(querybase, factbase),
InteGraalKeywords.Algorithms.OMQ_REWRITING);
CountingQueryEvaluator customizedEvaluator = QueryAnsweringComponentBuilder
.prepareAndGetCountingQueryAnsweringFrom(getQueries(), getFactbase(), getExternalHaltingConditions());
this.queryEvaluator = Optional.of(customizedEvaluator);
return customizedEvaluator;
}
/**
*
* Loads the data into the factbase.
* @return metadata describing the operation result
*
*/
public IOperationResult trySetFactBase() {
// note the abuse of switch notation
this.factbase = switch (factbase) {
case Optional o when kbscenario.getFactBase().isPresent() -> kbscenario.getFactBase();
case Optional o when kbscenario.getFactbasePaths().isPresent() ->
Optional.of(FactBaseLoaderFromFile.getFactbaseFor(kbscenario, integraalAlgorithmParameters));
case Optional o when kbscenario.getMappingbasePaths().isPresent() ->
Optional.of(FactBaseLoaderFromFile.getFederatedFactbaseFor(kbscenario, integraalAlgorithmParameters));
default -> {
LOG.warn("Asked to load factbase but no factbase input has been set.");
yield Optional.empty();
}
};
if (this.factbase.isPresent()) {
return new FactBaseLoadingOperationResult(this.factbase.get());
} else {
return new OperationNotPerformed(InteGraalKeywords.MonitoringOperations.LOAD_FACTBASE);
}
}
@Override
public void init() {
trySetFactBase();
trySetRuleBase();
trySetQueryBase();
tryCompileRuleset();
}
/**
* sets the rule base
*/
public IOperationResult trySetRuleBase() {
// note the abuse of switch notation
this.ruleset = switch (ruleset) {
case Optional> r when kbscenario.getRuleBase().isPresent() ->
// we create a new collection holding the rules in the provided rule base
Optional.of(new HashSet<>(kbscenario.getRuleBase().get().getRules()));
case Optional> r when kbscenario.getRulebasePath().isPresent() ->
Optional.of(DlgpParser.parseFiles(kbscenario.getRulebasePath().get()).rules());
default -> Optional.empty();
};
if (this.ruleset.isPresent()) {
return new RuleBaseLoadingOperationResult(new RuleBaseImpl(this.ruleset.get()));
} else {
return new OperationNotPerformed(InteGraalKeywords.MonitoringOperations.LOAD_RULEBASE);
}
}
/**
* sets the query base
*/
public IOperationResult trySetQueryBase() {
// note the abuse of switch notation
this.querybase = switch (querybase) {
case Optional> q when kbscenario.getQueryBase().isPresent() ->
Optional.of(kbscenario.getQueryBase().get());
case Optional> q when kbscenario.getQuerybasePaths().isPresent() ->
Optional.of(DlgpParser.parseFiles(kbscenario.getQuerybasePaths().get()).queries());
default -> Optional.empty();
};
if (this.querybase.isPresent()) {
return new QueryBaseLoadingOperationResult(this.querybase.get());
} else {
return new OperationNotPerformed(InteGraalKeywords.MonitoringOperations.LOAD_QUERY_WORKLOAD);
}
}
/**
* (if required) compiles the rules
*/
public IOperationResult tryCompileRuleset() {
if (ruleset.isEmpty() || integraalAlgorithmParameters.getCompilation().isEmpty()) {
// sanity check not passed
this.compilation = NoRuleCompilation.instance();
this.compilResult = Optional.empty();
return new OperationNotPerformed(InteGraalKeywords.Algorithms.RULE_COMPILATION);
}
this.compilation = switch (integraalAlgorithmParameters.getCompilation().get()) {
case HIERARCHICAL_COMPILATION -> new HierarchicalRuleCompilation();
case ID_COMPILATION -> new IDRuleCompilation();
default -> NoRuleCompilation.instance();
};
this.compilResult = Optional.ofNullable(compilation.compileAndGet(getRulebase()));
if (this.compilResult.isPresent()) {
return new RuleCompilationOperationResult(this.compilResult.get());
} else {
return new OperationNotPerformed(InteGraalKeywords.Algorithms.RULE_COMPILATION);
}
}
/**
* Checks that all necessary elements are present for component creation.
*
* @param list a list of optional elements to check.
* @param servicePrintOnly the name of the service being checked (optional).
* @throws IllegalArgumentException if any required element is missing.
*/
static void checkNecessaryElementsForComponent(List> list, Algorithms servicePrintOnly) {
if (list.stream().anyMatch(Optional::isEmpty)) {
throw new IllegalArgumentException("One of the elements for "
+ ((servicePrintOnly != null) ? servicePrintOnly : "unspecified-service") + " is undefined.");
}
}
///////////////////////////////
///////////////////////////////
///////////////////////////////
///////////////////////////////
/// PRIVATE METHODS
///////////////////////////////
///////////////////////////////
///////////////////////////////
///////////////////////////////
private void checkSaturationService() {
checkService(InteGraalKeywords.Algorithms.KB_CHASE, InteGraalKeywords.Algorithms.OMQA_CHASE,
InteGraalKeywords.Algorithms.QUERY_ANSWERING_VIA_HYBRID_STRATEGY);
}
private void checkRewritingService() {
checkService(InteGraalKeywords.Algorithms.OMQ_REWRITING, InteGraalKeywords.Algorithms.OMQA_REW,
InteGraalKeywords.Algorithms.QUERY_ANSWERING_VIA_HYBRID_STRATEGY);
}
private void checkQueryAnsweringService() {
checkService(InteGraalKeywords.Algorithms.QUERY_ANSWERING);
}
private void checkExists(Optional> singleObject) {
checkNecessaryElementsForComponent(List.of(singleObject), null);
}
/**
*
* Checks if the algorithm to run is compatible with the service.
*
* @param serviceList
*/
private void checkService(Algorithms... serviceList) {
boolean supportedService = false;
for (Algorithms service : serviceList) {
if (integraalAlgorithmParameters.getAlgorithm().equals(service)) {
supportedService = true;
}
}
if (!supportedService) {
throw new IllegalStateException("Unsupported service for " + integraalAlgorithmParameters.getAlgorithm());
}
}
private Duration getTimeout() {
return integraalAlgorithmParameters.getTimeout().isPresent() ? integraalAlgorithmParameters.getTimeout().get()
: null;
}
public void close() {
closeDatabaseConnectionsIfAny();
}
private void closeDatabaseConnectionsIfAny() {
if (this.factbase.isEmpty()) {
return;
}
if (this.factbase.get() instanceof RDBMSStore s) {
try {
s.getDriver().getConnection().close();
} catch (SQLException e) {
LOG.error("error while closing the database connection");
throw new RuntimeException(
String.format(
"[%s::closeDatabaseConnectionsIfAny] error while closing the database connection.",
this.getClass()));
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy