diff --git a/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/CECommands.java b/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/CECommands.java index 867a73a054a4f09496a1a52fb7aeea6116f73a92..332f1ecbe8ba7349cf09a8fd4c82142f3e3ed523 100644 --- a/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/CECommands.java +++ b/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/CECommands.java @@ -15,7 +15,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.jline.builtins.Less; @@ -1295,7 +1294,7 @@ public class CECommands { FederatedFactBase federation; try { - federation = new FederatedFactBase(StorageBuilder.defaultStorage(), ViewBuilder.createFactBases(this.mappingFilePath)); + federation = new FederatedFactBase(StorageBuilder.defaultStorage(), ViewBuilder.loadDataSources(this.mappingFilePath)); } catch (ViewBuilder.ViewBuilderException e) { IGRepl.writeIfVerbose("An error occurred while creating the federation using the view definition file.\n", PrintLevel.MAXIMAL); IGRepl.writeIfVerbose(e.getMessage(), PrintLevel.MAXIMAL); diff --git a/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/ComplexEnvironment.java b/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/ComplexEnvironment.java index a7b0a4843bc0ce82a1fd5e4e46e9f35bcb088ce2..1442b4511d19ac9d78e476c05a8c68450ab1e960 100644 --- a/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/ComplexEnvironment.java +++ b/integraal/integraal-api/src/main/java/fr/boreal/api/integraal_repl/ComplexEnvironment.java @@ -9,8 +9,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import fr.boreal.api.integraal_repl.CECommands.ComplexEnvironmentCommands; -import fr.boreal.api.integraal_repl.ComplexEnvironment.WriteMode; import fr.boreal.api.integraal_repl.IGRepl.PrintLevel; import fr.boreal.io.api.ParseException; import fr.boreal.io.dlgp.Directive; @@ -27,7 +25,6 @@ import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; import fr.boreal.model.query.api.FOQuery; import fr.boreal.model.query.api.Query; import fr.boreal.model.rule.api.FORule; -import fr.boreal.storage.builder.StorageBuilder; import fr.boreal.storage.natives.SimpleInMemoryGraphStore; import fr.boreal.views.FederatedFactBase; import fr.boreal.views.builder.ViewBuilder; @@ -540,7 +537,7 @@ public class ComplexEnvironment { FederatedFactBase federation; if (factbase == null) factbase = new SimpleInMemoryGraphStore(); try { - federation = new FederatedFactBase(factbase, ViewBuilder.createFactBases(vdPath.toString())); + federation = new FederatedFactBase(factbase, ViewBuilder.loadDataSources(vdPath.toString())); this.putFactBase(factBaseName, federation, mode); } catch (ViewBuilderException e) { IGRepl.writeIfVerbose("An error occurred while parsing the view definition file. Skipping.\n", PrintLevel.MAXIMAL); diff --git a/integraal/integraal-api/src/test/java/fr/boreal/explanation/api/EndUserAPITest.java b/integraal/integraal-api/src/test/java/fr/boreal/explanation/api/EndUserAPITest.java index 42b6f7a5561b811ece928d0591a0ada06b291b79..269479bcd1952504921940bf0a08dab63ffc3fce 100644 --- a/integraal/integraal-api/src/test/java/fr/boreal/explanation/api/EndUserAPITest.java +++ b/integraal/integraal-api/src/test/java/fr/boreal/explanation/api/EndUserAPITest.java @@ -64,7 +64,7 @@ class EndUserAPITest { c.createStatement().execute("INSERT INTO p VALUES('e', 'e');"); federation = new FederatedFactBase(StorageBuilder.defaultStorage(), - ViewBuilder.createFactBases(viewDefinitionFile.toString())); + ViewBuilder.loadDataSources(viewDefinitionFile.toString())); ParserResult parserResult = DlgpParser.parseFile(dlgpFile.toString()); memory_save = parserResult.atoms(); diff --git a/integraal/integraal-api/src/test/java/views/ViewTest.java b/integraal/integraal-api/src/test/java/views/ViewTest.java index 210c094d4f9492fadb67337a1a9e95c895de2bfe..ef42d7327af300ade9e3670d3021cfc3266909c9 100644 --- a/integraal/integraal-api/src/test/java/views/ViewTest.java +++ b/integraal/integraal-api/src/test/java/views/ViewTest.java @@ -6,6 +6,7 @@ import java.util.stream.Stream; import fr.boreal.model.data.readable.exception.EvaluationException; import fr.boreal.model.logicalElements.api.Substitution; +import fr.boreal.views.datasource.DataSource; import org.junit.Assert; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; @@ -27,7 +28,7 @@ import fr.boreal.query_evaluation.generic.GenericFOQueryEvaluator; import fr.boreal.storage.builder.StorageBuilder; import fr.boreal.views.FederatedFactBase; import fr.boreal.views.builder.ViewBuilder; -import fr.boreal.views.datasource.AbstractViewWrapper; +import fr.boreal.views.datasource.AbstractDataSource; @RunWith(Parameterized.class) class ViewTest { @@ -59,7 +60,7 @@ class ViewTest { @ParameterizedTest(name = "{index}: querying {1} on {0} should work ...") @MethodSource("data") public void dlgpViewSupportWithQueryEvaluation(String vdFilePath, FOQuery<?> query) throws ViewBuilder.ViewBuilderException { - Collection<AbstractViewWrapper<String, ?>> wrappers = ViewBuilder.createFactBases(vdFilePath); + Collection<DataSource<String, ?>> wrappers = ViewBuilder.loadDataSources(vdFilePath); FederatedFactBase fb = new FederatedFactBase(StorageBuilder.defaultStorage(), wrappers); Iterator<Substitution> results = null; try { @@ -79,7 +80,7 @@ class ViewTest { @ParameterizedTest(name = "{index}: querying {1} on {0} should work ...") @MethodSource("data") public void dlgpViewSupportWithAPIQueryEvaluation(String vdFilePath, FOQuery<?> query) throws ViewBuilder.ViewBuilderException { - Collection<AbstractViewWrapper<String, ?>> wrappers = ViewBuilder.createFactBases(vdFilePath); + Collection<DataSource<String, ?>> wrappers = ViewBuilder.loadDataSources(vdFilePath); FederatedFactBase fb = new FederatedFactBase(StorageBuilder.defaultStorage(), wrappers); var results = EndUserAPI.evaluateOld(fb, query); int count = 0; diff --git a/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/ChaseComponentBuilder.java b/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/ChaseComponentBuilder.java index 4ab33e367ce2bd683f2c263653e8800a8f3f0582..0589ca389a95a7d205389a4532531e3e10c78749 100644 --- a/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/ChaseComponentBuilder.java +++ b/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/ChaseComponentBuilder.java @@ -26,9 +26,9 @@ public class ChaseComponentBuilder { * * @return the prepared instance of the Chase algorithm. */ - public static Chase prepareAndGetChaseFrom(FactBase fb, RuleBase rb, IAlgorithmParameters chaseParams) { + public static Chase<FactBase> prepareAndGetChaseFrom(FactBase fb, RuleBase rb, IAlgorithmParameters chaseParams) { - ChaseBuilder builder = ChaseBuilder.defaultBuilder(fb, rb); + ChaseBuilder<FactBase> builder = ChaseBuilder.defaultBuilder(fb, rb); // SCHEDULER @@ -98,9 +98,7 @@ public class ChaseComponentBuilder { builder.addHaltingConditions(new Timeout(timeout.get().toMillis())); } - Chase customizedChase = builder.build().get(); - - return customizedChase; + return builder.build().orElseThrow(); } diff --git a/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/FactBaseLoaderFromFile.java b/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/FactBaseLoaderFromFile.java index d77fb2a764f2ee15496f79f43ad8c0b3811aa2f0..e441913359ab55aee06e245f3998ae6383fae201 100644 --- a/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/FactBaseLoaderFromFile.java +++ b/integraal/integraal-component/src/main/java/fr/boreal/component_builder/components/FactBaseLoaderFromFile.java @@ -80,7 +80,7 @@ public class FactBaseLoaderFromFile { public static FactBase getFederatedFactbaseFor(IInputDataScenario kbscenario, IAlgorithmParameters integraalAlgorithmParameters) { try { - return new FederatedFactBase(StorageBuilder.defaultStorage(), ViewBuilder.createFactBases(kbscenario.getMappingbasePaths().get())); + return new FederatedFactBase(StorageBuilder.defaultStorage(), ViewBuilder.loadDataSources(kbscenario.getMappingbasePaths().get())); } catch (ViewBuilder.ViewBuilderException e) { LOG.error(e.getMessage()); throw new RuntimeException( diff --git a/integraal/integraal-component/src/main/java/fr/boreal/component_builder/operations/ChaseRunOperationResult.java b/integraal/integraal-component/src/main/java/fr/boreal/component_builder/operations/ChaseRunOperationResult.java index b33fb6aa94248320550b865af58c7a138ed4082d..96a14e41120f245f6f8cd16febfdc2303542e5d8 100644 --- a/integraal/integraal-component/src/main/java/fr/boreal/component_builder/operations/ChaseRunOperationResult.java +++ b/integraal/integraal-component/src/main/java/fr/boreal/component_builder/operations/ChaseRunOperationResult.java @@ -4,6 +4,7 @@ import java.io.Serializable; import fr.boreal.component_builder.api.IOperationResult; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.kb.api.FactBase; /** * records the size of the chase result @@ -18,8 +19,8 @@ public record ChaseRunOperationResult(long size) implements IOperationResult, Se * * @param chase */ - public ChaseRunOperationResult(Chase chase) { - this(chase.getFactBase().size()); + public ChaseRunOperationResult(Chase<?> chase) { + this(chase.getChasableData().getWritingTarget().size()); } public String serializationString() { diff --git a/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceAndVariableCoreProcessor.java b/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceAndVariableCoreProcessor.java index b5bdd59ef33da19dc5e89b73f971857aa20c3881..61708d79888890691692be67f93bd91e41c472b3 100644 --- a/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceAndVariableCoreProcessor.java +++ b/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceAndVariableCoreProcessor.java @@ -37,7 +37,7 @@ import java.util.stream.Collectors; */ -public class ByPieceAndVariableCoreProcessor implements CoreProcessor { +public class ByPieceAndVariableCoreProcessor implements CoreProcessor<FactBase> { private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; public ByPieceAndVariableCoreProcessor() { diff --git a/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceCoreProcessor.java b/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceCoreProcessor.java index 35fc984c897aaa361ace01048f2d09c3d24fbea2..484b5735418ae5d3b72deccf8801a181a81bedeb 100644 --- a/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceCoreProcessor.java +++ b/integraal/integraal-core/src/main/java/fr/boreal/core/ByPieceCoreProcessor.java @@ -1,10 +1,11 @@ package fr.boreal.core; +import fr.boreal.model.data.readable.MaterializedData; import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.formula.api.FOFormulaConjunction; import fr.boreal.model.formula.factory.FOFormulaFactory; -import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; @@ -38,9 +39,9 @@ import java.util.stream.Collectors; * */ -public class ByPieceCoreProcessor implements CoreProcessor { +public class ByPieceCoreProcessor<RW extends MaterializedData & Writable> implements CoreProcessor<RW> { private final Variant variant; // Variant of the algorithm to use - private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; + private final FOQueryEvaluator<FOFormula, ? super RW> evaluator; public enum Variant { EXHAUSTIVE, @@ -48,7 +49,7 @@ public class ByPieceCoreProcessor implements CoreProcessor { BY_DELETION } - public ByPieceCoreProcessor(Variant variant, FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public ByPieceCoreProcessor(Variant variant, FOQueryEvaluator<FOFormula, ? super RW> evaluator) { this.variant = variant; this.evaluator = evaluator; } @@ -57,7 +58,7 @@ public class ByPieceCoreProcessor implements CoreProcessor { this(variant, GenericFOQueryEvaluator.defaultInstance()); } - public ByPieceCoreProcessor(FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public ByPieceCoreProcessor(FOQueryEvaluator<FOFormula, ? super RW> evaluator) { this(Variant.BY_DELETION, evaluator); } @@ -66,7 +67,7 @@ public class ByPieceCoreProcessor implements CoreProcessor { } @Override - public void computeCore(FactBase fb, Set<Variable> frozenVariables) { + public void computeCore(RW fb, Set<Variable> frozenVariables) { // We need to compute the set of all variables that are not frozen // The pieces of "a" will be computed with these variables Set<Variable> notFrozenVariables = new HashSet<>( @@ -103,7 +104,7 @@ public class ByPieceCoreProcessor implements CoreProcessor { } private void retractPiecesByDeletion ( - FactBase fb, + RW fb, SimpleInMemoryGraphStore p, Substitution frozenVariablesSubstitution, Set<Variable> frozenVariables) { @@ -168,7 +169,7 @@ public class ByPieceCoreProcessor implements CoreProcessor { } private void retractPiecesBySpecialisation ( - FactBase fb, + RW fb, SimpleInMemoryGraphStore p, Substitution frozenVariablesSubstitution, Set<Variable> frozenVariables) { @@ -245,11 +246,11 @@ public class ByPieceCoreProcessor implements CoreProcessor { } } - removeFromFactBase(toRemove, p, fb); + removeFromRW(toRemove, p, fb); } private void retractPiecesExhaustive ( - FactBase fb, + RW fb, SimpleInMemoryGraphStore p, Substitution frozenVariablesSubstitution, Set<Variable> frozenVariables) { @@ -300,10 +301,10 @@ public class ByPieceCoreProcessor implements CoreProcessor { } } - removeFromFactBase(toRemove, p, fb); + removeFromRW(toRemove, p, fb); } - private void removeFromFactBase(Set<Variable> toRemove, SimpleInMemoryGraphStore p, FactBase fb) { + private void removeFromRW(Set<Variable> toRemove, SimpleInMemoryGraphStore p, RW fb) { for (Variable v : toRemove) { Iterator<Atom> it_var = p.getAtomsByTerm(v).iterator(); while (it_var.hasNext()) { diff --git a/integraal/integraal-core/src/main/java/fr/boreal/core/CoreProcessor.java b/integraal/integraal-core/src/main/java/fr/boreal/core/CoreProcessor.java index c045c6d16c3a20cd50a764780edce8136e0a7f45..caa14aa385f77c1708cef8d7c670ed9c81e88564 100644 --- a/integraal/integraal-core/src/main/java/fr/boreal/core/CoreProcessor.java +++ b/integraal/integraal-core/src/main/java/fr/boreal/core/CoreProcessor.java @@ -1,5 +1,7 @@ package fr.boreal.core; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Variable; @@ -15,22 +17,22 @@ import java.util.Set; * */ -public interface CoreProcessor { +public interface CoreProcessor<RW extends MaterializedData & Writable> { /** * Compute the core of a fact base by removing all the redundant atoms in it * - * @param fb the fact base on which we want to compute the core + * @param writableData the data on which we want to compute the core */ - default void computeCore(FactBase fb) { - computeCore(fb, new HashSet<>()); + default void computeCore(RW writableData) { + computeCore(writableData, new HashSet<>()); } /** * Compute the core of a fact base by removing all the redundant atoms in it, in considering the frozen variables as constants, * these variables must belong to the core. * - * @param fb the fact base on which we want to compute the core + * @param writableData the writable data on which we want to compute the core * @param frozenVariables Variables that will be treated as constants */ - void computeCore(FactBase fb, Set<Variable> frozenVariables); + void computeCore(RW writableData, Set<Variable> frozenVariables); } diff --git a/integraal/integraal-core/src/main/java/fr/boreal/core/MultiThreadsByPieceCoreProcessor.java b/integraal/integraal-core/src/main/java/fr/boreal/core/MultiThreadsByPieceCoreProcessor.java index e5465a4ba8e66c0f136f60d1bb26284c73b68762..a7a2387d8622e2cc9867b8218152d8ad7e306e2e 100644 --- a/integraal/integraal-core/src/main/java/fr/boreal/core/MultiThreadsByPieceCoreProcessor.java +++ b/integraal/integraal-core/src/main/java/fr/boreal/core/MultiThreadsByPieceCoreProcessor.java @@ -1,10 +1,11 @@ package fr.boreal.core; +import fr.boreal.model.data.readable.MaterializedData; import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.formula.api.FOFormulaConjunction; import fr.boreal.model.formula.factory.FOFormulaFactory; -import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; @@ -43,12 +44,12 @@ import java.util.stream.Collectors; * */ -public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { - private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; +public class MultiThreadsByPieceCoreProcessor<RW extends MaterializedData & Writable> implements CoreProcessor<RW> { + private final FOQueryEvaluator<FOFormula, ? super RW> evaluator; Set<Variable> deletedVariables; // Set of variables that will be deleted at the end of the execution Set<Variable> frozenVariables; // Set of variables that will not be retracted Set<Variable> notFrozenVariables; // Complementary of frozenVariables - FactBase target; // Fact base on which we compute the core + RW target; // Fact base on which we compute the core Queue<SimpleInMemoryGraphStore> piecesQueue; // Queue to send pieces to the threads List<Thread> threads; // List of the threads @@ -68,7 +69,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { * @param limitNbThreads Maximum number of threads * @param variant Variant of the algorithm */ - public MultiThreadsByPieceCoreProcessor(FOQueryEvaluator<FOFormula, ? super FactBase> evaluator, long limitNbThreads, Variant variant) { + public MultiThreadsByPieceCoreProcessor(FOQueryEvaluator<FOFormula, ? super RW> evaluator, long limitNbThreads, Variant variant) { this.evaluator = evaluator; this.variant = variant; this.limitNbThreads = limitNbThreads; @@ -88,7 +89,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { * @param limitNbThreads Maximum number of threads * @param evaluator Query evaluator */ - public MultiThreadsByPieceCoreProcessor(long limitNbThreads, FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public MultiThreadsByPieceCoreProcessor(long limitNbThreads, FOQueryEvaluator<FOFormula, ? super RW> evaluator) { this(evaluator, limitNbThreads, Variant.BY_DELETION); } @@ -97,7 +98,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { } @Override - public void computeCore(FactBase fb, Set<Variable> frozenVariables) { + public void computeCore(RW fb, Set<Variable> frozenVariables) { // We initialize the attributes of the object init(fb, frozenVariables); @@ -142,7 +143,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { * @param fb the fact base which we compute the core * @param frozenVariables Set of variables that will not be retracted */ - private void init(FactBase fb, Set<Variable> frozenVariables) { + private void init(RW fb, Set<Variable> frozenVariables) { // We need to compute the set of all variables that are not frozen // The pieces of "a" will be computed with these variables notFrozenVariables = new HashSet<>(); @@ -226,7 +227,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { } } - private Iterator<Substitution> computeHomomorphismsToFactBase( + private Iterator<Substitution> computeHomomorphismsToRW( SimpleInMemoryGraphStore p, Substitution frozenVariablesSubstitution) { FOQuery<FOFormulaConjunction> q = FOQueryFactory.instance().createOrGetQuery( FOFormulaFactory.instance().createOrGetConjunction(p), null); @@ -262,7 +263,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { private void retractPiecesExhaustive (SimpleInMemoryGraphStore p, Substitution frozenVariablesSubstitution) throws InterruptedException { // We get an iterator on the retractions of the piece into the atom set target - Iterator<Substitution> it = computeHomomorphismsToFactBase(p, frozenVariablesSubstitution); + Iterator<Substitution> it = computeHomomorphismsToRW(p, frozenVariablesSubstitution); // Variables of p Set<Variable> pVars = p.getVariables().collect(Collectors.toSet()); @@ -316,7 +317,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { private void retractPiecesByDeletion (SimpleInMemoryGraphStore p, Substitution frozenVariablesSubstitution) throws InterruptedException { // We get an iterator on the retractions of the piece into the atom set target - Iterator<Substitution> it = computeHomomorphismsToFactBase(p, frozenVariablesSubstitution); + Iterator<Substitution> it = computeHomomorphismsToRW(p, frozenVariablesSubstitution); // Variables of p Set<Variable> pVars = p.getVariables().collect(Collectors.toSet()); @@ -372,7 +373,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { pVars.removeAll(deletedVars); // And we begin new research of retractions - it = computeHomomorphismsToFactBase(p, frozenVariablesSubstitution); + it = computeHomomorphismsToRW(p, frozenVariablesSubstitution); } } } @@ -381,7 +382,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { private void retractPiecesBySpecialisation (SimpleInMemoryGraphStore p, Substitution frozenVariablesSubstitution) throws InterruptedException { // We get an iterator on the retractions of the piece into the atom set target - Iterator<Substitution> it = computeHomomorphismsToFactBase(p, frozenVariablesSubstitution); + Iterator<Substitution> it = computeHomomorphismsToRW(p, frozenVariablesSubstitution); // Variables of p Set<Variable> pVars = p.getVariables().collect(Collectors.toSet()); @@ -447,7 +448,7 @@ public class MultiThreadsByPieceCoreProcessor implements CoreProcessor { } // And we begin new research of retractions - it = computeHomomorphismsToFactBase(p, frozenVariablesSubstitution); + it = computeHomomorphismsToRW(p, frozenVariablesSubstitution); } } } diff --git a/integraal/integraal-core/src/main/java/fr/boreal/core/NaiveCoreProcessor.java b/integraal/integraal-core/src/main/java/fr/boreal/core/NaiveCoreProcessor.java index 9e8642c550dc0cc5b9c991e22a339fb12bd70d1b..be16e16e6ecf77656a7674027ac5fdcb7bc0886a 100644 --- a/integraal/integraal-core/src/main/java/fr/boreal/core/NaiveCoreProcessor.java +++ b/integraal/integraal-core/src/main/java/fr/boreal/core/NaiveCoreProcessor.java @@ -19,7 +19,7 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; -public class NaiveCoreProcessor implements CoreProcessor { +public class NaiveCoreProcessor implements CoreProcessor<FactBase> { private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; public NaiveCoreProcessor() { diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/Chase.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/Chase.java index 35ad932f9c63ad8a6cd93ec719ce13d571171c37..a6786264fa5d9e53592c3b93d0f28793b57544c3 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/Chase.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/Chase.java @@ -1,16 +1,19 @@ package fr.boreal.forward_chaining.chase; import fr.boreal.forward_chaining.api.ForwardChainingAlgorithm; +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.rule_scheduler.RuleScheduler; -import fr.boreal.model.kb.api.FactBase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.RuleBase; /** - * The Chase is a way to saturate a {@link FactBase} according to rules + * The Chase is a way to saturate a {@link ChasableData} according to rules * * The work done for the modeling and implementation of the Chase is mostly part of Guillaume Pérution-Kihli internship's work (2020) */ -public interface Chase extends ForwardChainingAlgorithm { +public interface Chase<RW extends MaterializedData & Writable> extends ForwardChainingAlgorithm { /** * @return true iff this chase has a next step @@ -62,9 +65,9 @@ public interface Chase extends ForwardChainingAlgorithm { ///////////////////////////////// /** - * @return the factbase of this chase + * @return the ChasableData of this chase */ - FactBase getFactBase(); + ChasableData<RW> getChasableData(); /** * @return the rulebase of this chase diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseBuilder.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseBuilder.java index 28d087e350720083c13c1895ad0cdea1c84b152e..031fbd4856b69a89a333162828f8fcfbe155e280 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseBuilder.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseBuilder.java @@ -1,5 +1,7 @@ package fr.boreal.forward_chaining.chase; +import fr.boreal.forward_chaining.chase.data.ChasableData; +import fr.boreal.forward_chaining.chase.data.ChasableDataImpl; import fr.boreal.forward_chaining.chase.halting_condition.CreatedFactsAtPreviousStep; import fr.boreal.forward_chaining.chase.halting_condition.HaltingCondition; import fr.boreal.forward_chaining.chase.halting_condition.HasRulesToApply; @@ -26,6 +28,9 @@ import fr.boreal.forward_chaining.chase.treatment.AddCreatedFacts; import fr.boreal.forward_chaining.chase.treatment.Debug; import fr.boreal.forward_chaining.chase.treatment.EndTreatment; import fr.boreal.forward_chaining.chase.treatment.Pretreatment; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.kb.api.RuleBase; @@ -42,9 +47,9 @@ import java.util.*; * * Builder to create a parameterized chase algorithm */ -public class ChaseBuilder { +public class ChaseBuilder<RW extends MaterializedData & Writable> { - private FactBase fb; + private ChasableData<RW> chasableData; private RuleBase rb; private TermFactory tf = FactoryConstants.DEFAULT_TERM_FACTORY; @@ -52,11 +57,11 @@ public class ChaseBuilder { private Scheduler scheduler = Scheduler.GRD; private enum Scheduler {NAIVE, GRD} - private FOQueryEvaluator<FOFormula, ? super FactBase> eval; + private FOQueryEvaluator<FOFormula, QueryableData> eval; private Evaluator evaluator = Evaluator.GENERIC; private enum Evaluator {GENERIC, SMART} - private RuleApplier ra; + private RuleApplier<RW> ra; private Applier applier = Applier.BREADTH_FIRST_TRIGGER; private enum Applier {BREADTH_FIRST_TRIGGER, PARALLEL_TRIGGER, SOURCE_DELEGATED_DATALOG, MULTI_THREAD_TRIGGER} @@ -64,14 +69,14 @@ public class ChaseBuilder { private Transformer transformer = Transformer.FRONTIER; private enum Transformer {ALL, FRONTIER} - private TriggerComputer tc; + private TriggerComputer<RW> tc; private Computer computer = Computer.SEMI_NAIVE; private enum Computer {NAIVE, SEMI_NAIVE, TWO_STEP} - private TriggerChecker tch; + private TriggerChecker<RW> tch; private Checker checker = Checker.SEMI_OBLIVIOUS; private enum Checker {TRUE, OBLIVIOUS, SEMI_OBLIVIOUS, RESTRICTED, EQUIVALENT} - private TriggerApplier ta; - private FactsHandler fh; + private TriggerApplier<RW> ta; + private FactsHandler<RW> fh; private Application application = Application.DIRECT; private enum Application {DIRECT, PARALLEL} private TriggerRenamer renamer; @@ -79,11 +84,11 @@ public class ChaseBuilder { private enum Skolem {FRESH, BODY, FRONTIER, FRONTIER_PIECE} - private final List<HaltingCondition> hcs = new ArrayList<>(); - private final List<Pretreatment> global_pts = new ArrayList<>(); - private final List<Pretreatment> step_pts = new ArrayList<>(); - private final List<EndTreatment> global_end_ts = new ArrayList<>(); - private final List<EndTreatment> end_step_ts = new ArrayList<>(); + private final List<HaltingCondition<RW>> hcs = new ArrayList<>(); + private final List<Pretreatment<RW>> global_pts = new ArrayList<>(); + private final List<Pretreatment<RW>> step_pts = new ArrayList<>(); + private final List<EndTreatment<RW>> global_end_ts = new ArrayList<>(); + private final List<EndTreatment<RW>> end_step_ts = new ArrayList<>(); private boolean debug = false; @@ -93,7 +98,7 @@ public class ChaseBuilder { /** * The minimal configuration requires : <br> - * * a FactBase to saturate <br> + * * a QueryableWritableData to saturate <br> * * a RuleBase to get Rules from <br> * * a TermFactory to create new terms <br> * <br> @@ -111,9 +116,9 @@ public class ChaseBuilder { * * @return the created chase or an empty optional if the configuration is incorrect */ - public Optional<Chase> build() { + public Optional<Chase<RW>> build() { if(this.getMinimalConfig().isPresent()) { - return Optional.of(new ChaseImpl(fb, rb, rsc, ra, hcs, global_pts, step_pts, global_end_ts, end_step_ts)); + return Optional.of(new ChaseImpl<>(chasableData, rb, rsc, ra, hcs, global_pts, step_pts, global_end_ts, end_step_ts)); } else { return Optional.empty(); } @@ -129,9 +134,21 @@ public class ChaseBuilder { * @param rb the rule to apply * @return the builder initialized with the given parameters */ - public static ChaseBuilder defaultBuilder(FactBase fb, RuleBase rb) { - return new ChaseBuilder() - .setFactBase(fb) + public static ChaseBuilder<FactBase> defaultBuilder(FactBase fb, RuleBase rb) { + return defaultBuilder(new ChasableDataImpl<>(fb), rb); + } + + /** + * Builder initialized with the default chase and mandatory parameters + * @param chasableData the chasable data to saturate + * @param rb the rule to apply + * @return the builder initialized with the given parameters + */ + public static <RW extends MaterializedData & Writable> ChaseBuilder<RW> defaultBuilder( + ChasableData<RW> chasableData, + RuleBase rb) { + return new ChaseBuilder<RW>() + .setChasableData(chasableData) .setRuleBase(rb); } @@ -141,20 +158,32 @@ public class ChaseBuilder { * @param rb the rule to apply * @return the default chase initialized with the given parameters */ - public static Chase defaultChase(FactBase fb, RuleBase rb) { - return new ChaseBuilder() - .setFactBase(fb) + public static Chase<FactBase> defaultChase(FactBase fb, RuleBase rb) { + return defaultChase(new ChasableDataImpl<>(fb), rb); + } + + /** + * Chase initialized with the default parameters and the given mandatory parameters + * @param chasableData the chasable data to saturate + * @param rb the rule to apply + * @return the default chase initialized with the given parameters + */ + public static <RW extends MaterializedData & Writable> Chase<RW> defaultChase( + ChasableData<RW> chasableData, + RuleBase rb) { + return new ChaseBuilder<RW>() + .setChasableData(chasableData) .setRuleBase(rb) .build() - .get(); + .orElseThrow(); } ////////////////////// // Default settings // ////////////////////// - private Optional<ChaseBuilder> getMinimalConfig() { - if(this.fb == null) { + private Optional<ChaseBuilder<RW>> getMinimalConfig() { + if(this.chasableData == null) { return Optional.empty(); } if(this.rb == null) { @@ -186,18 +215,18 @@ public class ChaseBuilder { } if(this.tc == null) { switch (this.computer) { - case NAIVE : this.setTriggerComputer(new NaiveTriggerComputer(this.eval)); break; - case SEMI_NAIVE : this.setTriggerComputer(new SemiNaiveComputer(this.eval)); break; - case TWO_STEP : this.setTriggerComputer(new TwoStepComputer(this.eval)); break; + case NAIVE : this.setTriggerComputer(new NaiveTriggerComputer<>(this.eval)); break; + case SEMI_NAIVE : this.setTriggerComputer(new SemiNaiveComputer<>(this.eval)); break; + case TWO_STEP : this.setTriggerComputer(new TwoStepComputer<>(this.eval)); break; } } if(this.tch == null) { switch (this.checker) { - case TRUE : this.setTriggerChecker(new AlwaysTrueChecker()); break; - case OBLIVIOUS : this.setTriggerChecker(new ObliviousChecker()); break; - case SEMI_OBLIVIOUS : this.setTriggerChecker(new SemiObliviousChecker()); break; - case RESTRICTED : this.setTriggerChecker(new RestrictedChecker(this.eval)); break; - case EQUIVALENT : this.setTriggerChecker(new EquivalentChecker(this.eval)); break; + case TRUE : this.setTriggerChecker(new AlwaysTrueChecker<>()); break; + case OBLIVIOUS : this.setTriggerChecker(new ObliviousChecker<>()); break; + case SEMI_OBLIVIOUS : this.setTriggerChecker(new SemiObliviousChecker<>()); break; + case RESTRICTED : this.setTriggerChecker(new RestrictedChecker<>(this.eval)); break; + case EQUIVALENT : this.setTriggerChecker(new EquivalentChecker<>(this.eval)); break; } } if(this.ta == null) { @@ -211,11 +240,11 @@ public class ChaseBuilder { } if(this.fh == null) { switch(this.application) { - case DIRECT : this.setNewFactsHandler(new DirectApplication()); break; - case PARALLEL : this.setNewFactsHandler(new DelegatedApplication()); break; + case DIRECT : this.setNewFactsHandler(new DirectApplication<>()); break; + case PARALLEL : this.setNewFactsHandler(new DelegatedApplication<>()); break; } } - this.setTriggerApplier(new TriggerApplierImpl(this.renamer, this.fh)); + this.setTriggerApplier(new TriggerApplierImpl<>(this.renamer, this.fh)); } break; } @@ -223,20 +252,20 @@ public class ChaseBuilder { break; } switch(this.applier) { - case BREADTH_FIRST_TRIGGER : this.setRuleApplier(new BreadthFirstTriggerRuleApplier(this.transf, this.tc, this.tch, this.ta)); break; - case PARALLEL_TRIGGER : this.setRuleApplier(new ParallelTriggerRuleApplier(this.transf, this.tc, this.tch, this.ta)); break; - case SOURCE_DELEGATED_DATALOG : this.setRuleApplier(new SourceDelegatedDatalogRuleApplier()); break; - case MULTI_THREAD_TRIGGER : this.setRuleApplier(new MultiThreadRuleApplier(this.transf, this.tc, this.tch, this.ta)); break; + case BREADTH_FIRST_TRIGGER : this.setRuleApplier(new BreadthFirstTriggerRuleApplier<>(this.transf, this.tc, this.tch, this.ta)); break; + case PARALLEL_TRIGGER : this.setRuleApplier(new ParallelTriggerRuleApplier<>(this.transf, this.tc, this.tch, this.ta)); break; + case SOURCE_DELEGATED_DATALOG : this.setRuleApplier(new SourceDelegatedDatalogRuleApplier<>()); break; + case MULTI_THREAD_TRIGGER : this.setRuleApplier(new MultiThreadRuleApplier<>(this.transf, this.tc, this.tch, this.ta)); break; } } if(this.hcs.isEmpty()) { this.addStandardHaltingConditions(); } if(this.application == Application.PARALLEL) { - this.end_step_ts.addFirst(new AddCreatedFacts()); + this.end_step_ts.addFirst(new AddCreatedFacts<>()); } if(this.debug) { - this.addStepEndTreatments(new Debug()); + this.addStepEndTreatments(new Debug<>()); } return Optional.of(this); } @@ -251,7 +280,7 @@ public class ChaseBuilder { * Use a breadth first trigger applier * @return this */ - public ChaseBuilder useTriggerRuleApplier() { + public ChaseBuilder<RW> useTriggerRuleApplier() { this.applier = Applier.BREADTH_FIRST_TRIGGER; return this; } @@ -262,7 +291,7 @@ public class ChaseBuilder { * Use the generic query evaluator * @return this */ - public ChaseBuilder useGenericFOQueryEvaluator() { + public ChaseBuilder<RW> useGenericFOQueryEvaluator() { this.evaluator = Evaluator.GENERIC; return this; } @@ -271,7 +300,7 @@ public class ChaseBuilder { * Use the smart query evaluator * @return this */ - public ChaseBuilder useSmartFOQueryEvaluator() { + public ChaseBuilder<RW> useSmartFOQueryEvaluator() { this.evaluator = Evaluator.SMART; return this; } @@ -282,7 +311,7 @@ public class ChaseBuilder { * Use a naive rule scheduler * @return this */ - public ChaseBuilder useNaiveRuleScheduler() { + public ChaseBuilder<RW> useNaiveRuleScheduler() { this.scheduler = Scheduler.NAIVE; return this; } @@ -291,7 +320,7 @@ public class ChaseBuilder { * Use a rule scheduler based on the GRD * @return this */ - public ChaseBuilder useGRDRuleScheduler() { + public ChaseBuilder<RW> useGRDRuleScheduler() { this.scheduler = Scheduler.GRD; return this; } @@ -302,7 +331,7 @@ public class ChaseBuilder { * Use a transformation that keep all variables as answer variables when evaluating a rule's body * @return this */ - public ChaseBuilder useAllTransformer() { + public ChaseBuilder<RW> useAllTransformer() { this.transformer = Transformer.ALL; return this; } @@ -311,7 +340,7 @@ public class ChaseBuilder { * Use a transformation that keep only the variables of the frontier as answer variables when evaluating a rule's body * @return this */ - public ChaseBuilder useFrontierTransformer() { + public ChaseBuilder<RW> useFrontierTransformer() { this.transformer = Transformer.FRONTIER; return this; } @@ -322,7 +351,7 @@ public class ChaseBuilder { * Use a naive method to compute triggers * @return this */ - public ChaseBuilder useNaiveComputer() { + public ChaseBuilder<RW> useNaiveComputer() { this.computer = Computer.NAIVE; return this; } @@ -331,7 +360,7 @@ public class ChaseBuilder { * Use the semi naive method to compute triggers * @return this */ - public ChaseBuilder useSemiNaiveComputer() { + public ChaseBuilder<RW> useSemiNaiveComputer() { this.computer = Computer.SEMI_NAIVE; return this; } @@ -340,7 +369,7 @@ public class ChaseBuilder { * Use the two step method to compute triggers * @return this */ - public ChaseBuilder useTwoStepComputer() { + public ChaseBuilder<RW> useTwoStepComputer() { this.computer = Computer.TWO_STEP; return this; } @@ -351,7 +380,7 @@ public class ChaseBuilder { * Use a direct application of the triggers * @return this */ - public ChaseBuilder useDirectApplication() { + public ChaseBuilder<RW> useDirectApplication() { this.application = Application.DIRECT; this.applier = Applier.BREADTH_FIRST_TRIGGER; return this; @@ -361,7 +390,7 @@ public class ChaseBuilder { * Use a parallel application of the triggers * @return this */ - public ChaseBuilder useParallelApplication() { + public ChaseBuilder<RW> useParallelApplication() { this.application = Application.PARALLEL; this.applier = Applier.PARALLEL_TRIGGER; return this; @@ -373,7 +402,7 @@ public class ChaseBuilder { * * @return this */ - public ChaseBuilder useMultiThreadRuleApplier() { + public ChaseBuilder<RW> useMultiThreadRuleApplier() { this.application = Application.PARALLEL; this.applier = Applier.MULTI_THREAD_TRIGGER; return this; @@ -384,7 +413,7 @@ public class ChaseBuilder { * Use a method of delegating to the source the application of the datalog rules * @return this */ - public ChaseBuilder useSourceDelegatedDatalogApplication() { + public ChaseBuilder<RW> useSourceDelegatedDatalogApplication() { this.applier = Applier.SOURCE_DELEGATED_DATALOG; return this; } @@ -395,7 +424,7 @@ public class ChaseBuilder { * Use an always true criteria for the triggers * @return this */ - public ChaseBuilder useAlwaysTrueChecker() { + public ChaseBuilder<RW> useAlwaysTrueChecker() { this.checker = Checker.TRUE; return this; } @@ -404,7 +433,7 @@ public class ChaseBuilder { * Use a oblivious criteria for the triggers * @return this */ - public ChaseBuilder useObliviousChecker() { + public ChaseBuilder<RW> useObliviousChecker() { this.checker = Checker.OBLIVIOUS; return this; } @@ -413,7 +442,7 @@ public class ChaseBuilder { * Use a semi oblivious criteria for the triggers * @return this */ - public ChaseBuilder useSemiObliviousChecker() { + public ChaseBuilder<RW> useSemiObliviousChecker() { this.checker = Checker.SEMI_OBLIVIOUS; return this; } @@ -422,7 +451,7 @@ public class ChaseBuilder { * Use a restricted criteria for the triggers * @return this */ - public ChaseBuilder useRestrictedChecker() { + public ChaseBuilder<RW> useRestrictedChecker() { this.checker = Checker.RESTRICTED; return this; } @@ -431,7 +460,7 @@ public class ChaseBuilder { * Use an equivalent criteria for the triggers * @return this */ - public ChaseBuilder useEquivalentChecker() { + public ChaseBuilder<RW> useEquivalentChecker() { this.checker = Checker.EQUIVALENT; return this; } @@ -442,7 +471,7 @@ public class ChaseBuilder { * Use a fresh name for the existentials * @return this */ - public ChaseBuilder useFreshNaming() { + public ChaseBuilder<RW> useFreshNaming() { this.skolem = Skolem.FRESH; return this; } @@ -451,7 +480,7 @@ public class ChaseBuilder { * Use a skolem of the body as name for the existentials * @return this */ - public ChaseBuilder useBodySkolem() { + public ChaseBuilder<RW> useBodySkolem() { this.skolem = Skolem.BODY; return this; } @@ -460,7 +489,7 @@ public class ChaseBuilder { * Use a skolem of the body, limited to the frontier as name for the existentials * @return this */ - public ChaseBuilder useFrontierSkolem() { + public ChaseBuilder<RW> useFrontierSkolem() { this.skolem = Skolem.FRONTIER; return this; } @@ -469,7 +498,7 @@ public class ChaseBuilder { * Use a skolem of the body, limited to the frontier of the piece as name for the existentials * @return this */ - public ChaseBuilder useFrontierByPieceSkolem() { + public ChaseBuilder<RW> useFrontierByPieceSkolem() { this.skolem = Skolem.FRONTIER_PIECE; return this; } @@ -479,12 +508,12 @@ public class ChaseBuilder { ///////////// /** - * Sets the FactBase - * @param fb the FactBase + * Sets the QueryableWritableData + * @param chasableData the chasable data * @return this */ - public ChaseBuilder setFactBase(FactBase fb) { - this.fb = fb; + public ChaseBuilder<RW> setChasableData(ChasableData<RW> chasableData) { + this.chasableData = chasableData; return this; } @@ -493,7 +522,7 @@ public class ChaseBuilder { * @param rb the RuleBase * @return this */ - public ChaseBuilder setRuleBase(RuleBase rb) { + public ChaseBuilder<RW> setRuleBase(RuleBase rb) { this.rb = rb; return this; } @@ -503,7 +532,7 @@ public class ChaseBuilder { * @param tf the TermFactory * @return this */ - public ChaseBuilder setTermFactory(TermFactory tf) { + public ChaseBuilder<RW> setTermFactory(TermFactory tf) { this.tf = tf; return this; } @@ -513,7 +542,7 @@ public class ChaseBuilder { * @param rsc the RuleScheduler * @return this */ - public ChaseBuilder setRuleScheduler(RuleScheduler rsc) { + public ChaseBuilder<RW> setRuleScheduler(RuleScheduler rsc) { this.rsc = rsc; return this; } @@ -523,7 +552,8 @@ public class ChaseBuilder { * @param eval the FOQueryEvaluator * @return this */ - public ChaseBuilder setFOQueryEvaluator(FOQueryEvaluator<FOFormula, ? super FactBase> eval) { + public ChaseBuilder<RW> setFOQueryEvaluator( + FOQueryEvaluator<FOFormula, QueryableData> eval) { this.eval = eval; return this; } @@ -533,7 +563,7 @@ public class ChaseBuilder { * @param ra the RuleApplier * @return this */ - public ChaseBuilder setRuleApplier(RuleApplier ra) { + public ChaseBuilder<RW> setRuleApplier(RuleApplier<RW> ra) { this.ra = ra; return this; } @@ -545,7 +575,7 @@ public class ChaseBuilder { * @param transf the BodyToQueryTransformer * @return this */ - public ChaseBuilder setBodyToQueryTransformer(BodyToQueryTransformer transf) { + public ChaseBuilder<RW> setBodyToQueryTransformer(BodyToQueryTransformer transf) { this.transf = transf; return this; } @@ -555,7 +585,7 @@ public class ChaseBuilder { * @param tc the TriggerComputer * @return this */ - public ChaseBuilder setTriggerComputer(TriggerComputer tc) { + public ChaseBuilder<RW> setTriggerComputer(TriggerComputer<RW> tc) { this.tc = tc; return this; } @@ -565,7 +595,7 @@ public class ChaseBuilder { * @param tch the TriggerChecker * @return this */ - public ChaseBuilder setTriggerChecker(TriggerChecker tch) { + public ChaseBuilder<RW> setTriggerChecker(TriggerChecker<RW> tch) { this.tch = tch; return this; } @@ -575,7 +605,7 @@ public class ChaseBuilder { * @param ta the TriggerApplier * @return this */ - public ChaseBuilder setTriggerApplier(TriggerApplier ta) { + public ChaseBuilder<RW> setTriggerApplier(TriggerApplier<RW> ta) { this.ta = ta; return this; } @@ -585,7 +615,7 @@ public class ChaseBuilder { * @param tr the TriggerRenamer * @return this */ - public ChaseBuilder setExistentialsRenamer(TriggerRenamer tr) { + public ChaseBuilder<RW> setExistentialsRenamer(TriggerRenamer tr) { this.renamer = tr; return this; } @@ -595,7 +625,7 @@ public class ChaseBuilder { * @param fh the FactsHandler * @return this */ - public ChaseBuilder setNewFactsHandler(FactsHandler fh) { + public ChaseBuilder<RW> setNewFactsHandler(FactsHandler<RW> fh) { this.fh = fh; return this; } @@ -606,8 +636,8 @@ public class ChaseBuilder { * Adds the standard halting conditions * @return this */ - public ChaseBuilder addStandardHaltingConditions() { - this.addHaltingConditions(new CreatedFactsAtPreviousStep(), new HasRulesToApply()); + public ChaseBuilder<RW> addStandardHaltingConditions() { + this.addHaltingConditions(new CreatedFactsAtPreviousStep<>(), new HasRulesToApply<>()); return this; } @@ -616,7 +646,8 @@ public class ChaseBuilder { * @param hcs halting conditions * @return this */ - public ChaseBuilder addHaltingConditions(HaltingCondition... hcs) { + @SafeVarargs + public final ChaseBuilder<RW> addHaltingConditions(HaltingCondition<RW>... hcs) { this.hcs.addAll(Arrays.asList(hcs)); return this; } @@ -626,7 +657,7 @@ public class ChaseBuilder { * @param hcs halting conditions * @return this */ - public ChaseBuilder addHaltingConditions(Collection<HaltingCondition> hcs) { + public ChaseBuilder<RW> addHaltingConditions(Collection<HaltingCondition<RW>> hcs) { this.hcs.addAll(hcs); return this; } @@ -638,7 +669,8 @@ public class ChaseBuilder { * @param pts Global pretreatment * @return this */ - public ChaseBuilder addGlobalPretreatments(Pretreatment... pts) { + @SafeVarargs + public final ChaseBuilder<RW> addGlobalPretreatments(Pretreatment<RW>... pts) { this.global_pts.addAll(Arrays.asList(pts)); return this; } @@ -648,7 +680,7 @@ public class ChaseBuilder { * @param pts Global pretreatment * @return this */ - public ChaseBuilder addGlobalPretreatments(Collection<Pretreatment> pts) { + public ChaseBuilder<RW> addGlobalPretreatments(Collection<Pretreatment<RW>> pts) { this.global_pts.addAll(pts); return this; } @@ -660,7 +692,8 @@ public class ChaseBuilder { * @param pts Step pretreatment * @return this */ - public ChaseBuilder addStepPretreatments(Pretreatment... pts) { + @SafeVarargs + public final ChaseBuilder<RW> addStepPretreatments(Pretreatment<RW>... pts) { this.step_pts.addAll(Arrays.asList(pts)); return this; } @@ -670,7 +703,7 @@ public class ChaseBuilder { * @param pts Step pretreatment * @return this */ - public ChaseBuilder addStepPretreatments(Collection<Pretreatment> pts) { + public ChaseBuilder<RW> addStepPretreatments(Collection<Pretreatment<RW>> pts) { this.step_pts.addAll(pts); return this; } @@ -682,7 +715,7 @@ public class ChaseBuilder { * @param ets Step Global end treatement * @return this */ - public ChaseBuilder addGlobalEndTreatments(EndTreatment... ets) { + public ChaseBuilder<RW> addGlobalEndTreatments(EndTreatment<RW>... ets) { this.global_end_ts.addAll(Arrays.asList(ets)); return this; } @@ -692,7 +725,7 @@ public class ChaseBuilder { * @param ets Step Global end treatement * @return this */ - public ChaseBuilder addGlobalEndTreatments(Collection<EndTreatment> ets) { + public ChaseBuilder<RW> addGlobalEndTreatments(Collection<EndTreatment<RW>> ets) { this.global_end_ts.addAll(ets); return this; } @@ -704,7 +737,8 @@ public class ChaseBuilder { * @param ets Step end treatement * @return this */ - public ChaseBuilder addStepEndTreatments(EndTreatment... ets) { + @SafeVarargs + public final ChaseBuilder<RW> addStepEndTreatments(EndTreatment<RW>... ets) { this.end_step_ts.addAll(Arrays.asList(ets)); return this; } @@ -714,7 +748,7 @@ public class ChaseBuilder { * @param ets Step end treatement * @return this */ - public ChaseBuilder addStepEndTreatments(Collection<EndTreatment> ets) { + public ChaseBuilder<RW> addStepEndTreatments(Collection<EndTreatment<RW>> ets) { this.end_step_ts.addAll(ets); return this; } @@ -723,21 +757,21 @@ public class ChaseBuilder { * Adds the debug option * @return this */ - public ChaseBuilder debug() { + public ChaseBuilder<RW> debug() { this.debug = true; return this; } /** * Returns a StratifiedChaseBuilder for creating a StratifiedChase, with this ChaseBuilder in parameter. - * Transfers the FactBase and RuleBase if they are already set. + * Transfers the QueryableWritableData and RuleBase if they are already set. * * @return a new StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder useStratifiedChase() { - StratifiedChaseBuilder stratifiedChaseBuilder = new StratifiedChaseBuilder(this); - if (this.fb != null) { - stratifiedChaseBuilder.setFactBase(this.fb); + public StratifiedChaseBuilder<RW> useStratifiedChase() { + StratifiedChaseBuilder<RW> stratifiedChaseBuilder = new StratifiedChaseBuilder<RW>(this); + if (this.chasableData != null) { + stratifiedChaseBuilder.setChasableData(this.chasableData); } if (this.rb != null) { stratifiedChaseBuilder.setRuleBase(this.rb); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseImpl.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseImpl.java index ee83d0802f0f5d0a2fee7a50675bcf303a89523b..36ff06817e3cc352b37d8e5933655e5501f8b40a 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseImpl.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/ChaseImpl.java @@ -1,36 +1,38 @@ package fr.boreal.forward_chaining.chase; -import java.util.Collection; - +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.halting_condition.HaltingCondition; import fr.boreal.forward_chaining.chase.rule_applier.RuleApplier; import fr.boreal.forward_chaining.chase.rule_scheduler.RuleScheduler; import fr.boreal.forward_chaining.chase.treatment.EndTreatment; import fr.boreal.forward_chaining.chase.treatment.Pretreatment; import fr.boreal.forward_chaining.chase.treatment.Treatment; -import fr.boreal.model.kb.api.FactBase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.RuleBase; import fr.boreal.model.rule.api.FORule; +import java.util.Collection; + /** * Default implementation of the chase algorithm */ -public class ChaseImpl implements Chase { +public class ChaseImpl<RW extends MaterializedData & Writable> implements Chase<RW> { - private final FactBase fb; + private final ChasableData<RW> chasableData; private RuleBase rb; private final RuleScheduler rule_scheduler; - private final RuleApplier rule_applier; + private final RuleApplier<RW> rule_applier; private RuleApplicationStepResult last_step_result; - private final Collection<HaltingCondition> halting_conditions; + private final Collection<HaltingCondition<RW>> halting_conditions; - private final Collection<Pretreatment> global_pretreatments; - private final Collection<Pretreatment> step_pretreatments; + private final Collection<Pretreatment<RW>> global_pretreatments; + private final Collection<Pretreatment<RW>> step_pretreatments; - private final Collection<EndTreatment> global_end_treatments; - private final Collection<EndTreatment> end_of_step_treatments; + private final Collection<EndTreatment<RW>> global_end_treatments; + private final Collection<EndTreatment<RW>> end_of_step_treatments; private int step_number = 0; @@ -40,7 +42,7 @@ public class ChaseImpl implements Chase { /** * Use {@link ChaseBuilder} to create a chase - * @param fb the factbase + * @param chasableData the factbase * @param rb the rulebase * @param rule_scheduler the rule scheduler * @param rule_applier the rule applier @@ -50,14 +52,14 @@ public class ChaseImpl implements Chase { * @param global_end_treatments the global end treatments * @param end_of_step_treatments the end of step treatments */ - protected ChaseImpl(FactBase fb, RuleBase rb, - RuleScheduler rule_scheduler, RuleApplier rule_applier, - Collection<HaltingCondition> halting_conditions, - Collection<Pretreatment> global_pretreatments, - Collection<Pretreatment> step_pretreatments, - Collection<EndTreatment> global_end_treatments, - Collection<EndTreatment> end_of_step_treatments) { - this.fb = fb; + protected ChaseImpl(ChasableData<RW> chasableData, RuleBase rb, + RuleScheduler rule_scheduler, RuleApplier<RW> rule_applier, + Collection<HaltingCondition<RW>> halting_conditions, + Collection<Pretreatment<RW>> global_pretreatments, + Collection<Pretreatment<RW>> step_pretreatments, + Collection<EndTreatment<RW>> global_end_treatments, + Collection<EndTreatment<RW>> end_of_step_treatments) { + this.chasableData = chasableData; this.rb = rb; this.rule_scheduler = rule_scheduler; this.rule_applier = rule_applier; @@ -83,7 +85,7 @@ public class ChaseImpl implements Chase { public void nextStep() { ++step_number; Collection<FORule> rules_to_apply = this.rule_scheduler.getRulesToApply(this.last_step_result.applied_rules()); - this.last_step_result = this.rule_applier.apply(rules_to_apply, this.fb); + this.last_step_result = this.rule_applier.apply(rules_to_apply, this.chasableData); } @Override @@ -112,8 +114,8 @@ public class ChaseImpl implements Chase { ///////////////////////////////////////////////// @Override - public FactBase getFactBase() { - return this.fb; + public ChasableData<RW> getChasableData() { + return this.chasableData; } @Override @@ -146,7 +148,7 @@ public class ChaseImpl implements Chase { public String toString() { return "Steps : " + this.step_number + "\nStep result :\n" + this.last_step_result + - "\nFacts :\n" +this.fb.toString(); + "\nFacts :\n" +this.chasableData.toString(); } ///////////////////////////////////////////////// diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/data/ChasableData.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/data/ChasableData.java new file mode 100644 index 0000000000000000000000000000000000000000..8f41953577f9467af1cd7d77c6de7af3157293d6 --- /dev/null +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/data/ChasableData.java @@ -0,0 +1,50 @@ +package fr.boreal.forward_chaining.chase.data; + +import fr.boreal.model.data.collection.api.QueryableDataCollection; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; +import fr.boreal.model.logicalElements.api.Predicate; + +import java.util.Collection; +import java.util.Optional; + +/** + * Represents data on which we can apply the chase. + * There are two parts: a part read-only that can be any queryable and a part read-write that is materialized and writable. + * The chase writes data only in the second part. + * The read-write part cannot have predicates that are in the read-only part. + * @param <ReadWrite> Read-Write data that will contain the result of the chase + */ +public interface ChasableData<ReadWrite extends MaterializedData & Writable> { + /** + * Read-only data - the predicates are distinct from the read-write data + * @return the read-only data + */ + Optional<QueryableData> getDataSource(); + + /** + * Read-write data - the predicates are distinct from the read-only data + * @return the data that will notably contain the result of the chase + */ + ReadWrite getWritingTarget(); + + /** + * Checks the validity of the Chasable + * @return true if this Chasable is valid + */ + default boolean checkValidity() { + if (getDataSource().isEmpty()) { + return true; + } + + Collection<Predicate> readOnlyPredicates = getDataSource().get().getPredicates(); + return getWritingTarget().getPredicates().stream().noneMatch(readOnlyPredicates::contains); + } + + /** + * Get a queryable data collection containing both the read-only and the read-write data + * @return a queryable data collection containing all readable data + */ + QueryableData getAllReadableData(); +} diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/data/ChasableDataImpl.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/data/ChasableDataImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..e5c40ce5c70b88a0a39aeb16b7f72aeabaeb3575 --- /dev/null +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/data/ChasableDataImpl.java @@ -0,0 +1,52 @@ +package fr.boreal.forward_chaining.chase.data; + +import fr.boreal.model.data.collection.builder.ReadOnlyDataCollectionBuilder; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; + +import java.util.Optional; + +public class ChasableDataImpl<ReadWrite extends MaterializedData & Writable> + implements ChasableData<ReadWrite> { + private final QueryableData dataSource; + private final ReadWrite writingTarget; + private final QueryableData allReadableData; + + public ChasableDataImpl(ReadWrite writingTarget) { + this(null, writingTarget); + } + + public ChasableDataImpl(QueryableData dataSource, ReadWrite writingTarget) { + this.dataSource = dataSource; + this.writingTarget = writingTarget; + + if (dataSource != null) { + allReadableData = new ReadOnlyDataCollectionBuilder<>() + .addQueryableData(dataSource) + .addQueryableData(writingTarget) + .build(); + } else { + allReadableData = writingTarget; + } + + if (!checkValidity()) { + throw new IllegalArgumentException("The Chasable Data is not valid"); + } + } + + @Override + public Optional<QueryableData> getDataSource() { + return Optional.ofNullable(dataSource); + } + + @Override + public ReadWrite getWritingTarget() { + return writingTarget; + } + + @Override + public QueryableData getAllReadableData() { + return allReadableData; + } +} diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/CreatedFactsAtPreviousStep.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/CreatedFactsAtPreviousStep.java index 1f9a1b0a97ac0621f3e48b6947334419c48a1bb9..44b2d45292606961f16f469b497e08de29847fc4 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/CreatedFactsAtPreviousStep.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/CreatedFactsAtPreviousStep.java @@ -1,13 +1,17 @@ package fr.boreal.forward_chaining.chase.halting_condition; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; /** * This halting condition stops the chase if no facts were created at the last step */ -public class CreatedFactsAtPreviousStep implements HaltingCondition { +public class CreatedFactsAtPreviousStep<RW extends MaterializedData & Writable> + implements HaltingCondition<RW> { - private Chase c; + private Chase<RW> c; @Override public boolean check() { @@ -19,7 +23,7 @@ public class CreatedFactsAtPreviousStep implements HaltingCondition { } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.c = c; } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HaltingCondition.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HaltingCondition.java index 72942ff935bf973b1f4e225ed1cebbea3cbb7360..9670ba69343ee1ed2ba616e18a46d61117fe6cb1 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HaltingCondition.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HaltingCondition.java @@ -1,17 +1,20 @@ package fr.boreal.forward_chaining.chase.halting_condition; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; /** * The Halting condition computes if there is a need for a next chase step or if it stops */ -public interface HaltingCondition { +public interface HaltingCondition<RW extends MaterializedData & Writable> { /** * Initialize the halting condition for the given chase * @param c the Chase object */ - void init(Chase c); + void init(Chase<RW> c); /** * @return true iff the condition is respected diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HasRulesToApply.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HasRulesToApply.java index d0dac56ad80328cdea49ddbafb441f25da1e7d12..7813c8962f54c1d6cd11b06b9c85cf016e578810 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HasRulesToApply.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/HasRulesToApply.java @@ -1,13 +1,17 @@ package fr.boreal.forward_chaining.chase.halting_condition; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; /** * This halting condition stops the chase if no rules need to be applied according to the scheduler */ -public class HasRulesToApply implements HaltingCondition { +public class HasRulesToApply<RW extends MaterializedData & Writable> + implements HaltingCondition<RW> { - Chase c; + Chase<RW> c; @Override public boolean check() { @@ -15,7 +19,7 @@ public class HasRulesToApply implements HaltingCondition { } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.c = c; } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitAtoms.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitAtoms.java index 0e232401544c06c08acfd253da7109086cfdc49f..e2f900e8d4959f17da0ffd29fc226f8d649a457f 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitAtoms.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitAtoms.java @@ -1,13 +1,17 @@ package fr.boreal.forward_chaining.chase.halting_condition; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; /** - * This halting condition stops the chase if there is more than a given number of atoms on the factbase + * This halting condition stops the chase if there is more than a given number of atoms on the writable data */ -public class LimitAtoms implements HaltingCondition { +public class LimitAtoms<RW extends MaterializedData & Writable> + implements HaltingCondition<RW> { - private Chase c; + private Chase<RW> c; private final long nbLimitAtoms; /** @@ -19,11 +23,11 @@ public class LimitAtoms implements HaltingCondition { @Override public boolean check() { - return c.getFactBase().size() < this.nbLimitAtoms; + return c.getChasableData().getWritingTarget().size() < this.nbLimitAtoms; } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.c = c; } } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitNumberOfStep.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitNumberOfStep.java index 090eab031a7956e243b3936f6ed5f788c6f10823..135c85fe9d761800ad2171d33df949a512348ad8 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitNumberOfStep.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/LimitNumberOfStep.java @@ -1,13 +1,17 @@ package fr.boreal.forward_chaining.chase.halting_condition; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; /** * This halting condition stops the chase if it reaches a given number a steps */ -public class LimitNumberOfStep implements HaltingCondition { +public class LimitNumberOfStep<RW extends MaterializedData & Writable> + implements HaltingCondition<RW> { - private Chase c; + private Chase<RW> c; private final int max; @@ -24,7 +28,7 @@ public class LimitNumberOfStep implements HaltingCondition { } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.c = c; } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/Timeout.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/Timeout.java index 90c603b9a1ddde7bce30bf3a0a1258360b4932d6..4821134370152d95a0824a0a88a309b5b88fb07c 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/Timeout.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/halting_condition/Timeout.java @@ -1,11 +1,15 @@ package fr.boreal.forward_chaining.chase.halting_condition; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; /** * This halting condition stops the chase if more than a given amount of time passed */ -public class Timeout implements HaltingCondition { +public class Timeout<RW extends MaterializedData & Writable> + implements HaltingCondition<RW> { private final long timeout; private long start_time; @@ -24,7 +28,7 @@ public class Timeout implements HaltingCondition { } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.start_time = System.nanoTime(); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChase.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChase.java index 10b6b49798e90dabdf723219bf83c52694476c37..09ce910c4284e4455f284d8827e989aff515b2c1 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChase.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChase.java @@ -3,47 +3,51 @@ package fr.boreal.forward_chaining.chase.metachase.stratified; import fr.boreal.forward_chaining.chase.Chase; import fr.boreal.forward_chaining.chase.ChaseBuilder; import fr.boreal.forward_chaining.chase.RuleApplicationStepResult; +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.halting_condition.HaltingCondition; import fr.boreal.forward_chaining.chase.rule_scheduler.RuleScheduler; import fr.boreal.forward_chaining.chase.treatment.EndTreatment; import fr.boreal.forward_chaining.chase.treatment.Pretreatment; import fr.boreal.forward_chaining.chase.treatment.Treatment; -import fr.boreal.model.kb.api.FactBase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.RuleBase; import java.util.Collection; import java.util.List; import java.util.Optional; -public class StratifiedChase implements Chase { - private final FactBase fb; +public class StratifiedChase<RW extends MaterializedData & Writable> + implements Chase<RW> { + private final ChasableData<RW> chasableData; private List<RuleBase> strata; - private final ChaseBuilder chaseBuilder; - private Chase chase; + private final ChaseBuilder<RW> chaseBuilder; + private Chase<RW> chase; - private final Collection<HaltingCondition> halting_conditions; + private final Collection<HaltingCondition<RW>> halting_conditions; - private final Collection<Pretreatment> global_pretreatments; - private final Collection<Pretreatment> step_pretreatments; + private final Collection<Pretreatment<RW>> global_pretreatments; + private final Collection<Pretreatment<RW>> step_pretreatments; - private final Collection<EndTreatment> global_end_treatments; - private final Collection<EndTreatment> end_of_step_treatments; + private final Collection<EndTreatment<RW>> global_end_treatments; + private final Collection<EndTreatment<RW>> end_of_step_treatments; private int step_number = 0; - public StratifiedChase(ChaseBuilder builder, FactBase fb, + public StratifiedChase(ChaseBuilder<RW> builder, ChasableData<RW> chasableData, List<RuleBase> strata, - Collection<HaltingCondition> halting_conditions, - Collection<Pretreatment> global_pretreatments, - Collection<Pretreatment> step_pretreatments, - Collection<EndTreatment> global_end_treatments, - Collection<EndTreatment> end_of_step_treatments) { - this.fb = fb; + Collection<HaltingCondition<RW>> halting_conditions, + Collection<Pretreatment<RW>> global_pretreatments, + Collection<Pretreatment<RW>> step_pretreatments, + Collection<EndTreatment<RW>> global_end_treatments, + Collection<EndTreatment<RW>> end_of_step_treatments) { + this.chasableData = chasableData; this.strata = strata; this.chaseBuilder = builder; - this.chaseBuilder.setFactBase(fb); + this.chaseBuilder.setChasableData(chasableData); this.halting_conditions = halting_conditions; this.global_pretreatments = global_pretreatments; @@ -59,7 +63,7 @@ public class StratifiedChase implements Chase { @Override public void nextStep() { - Optional<Chase> optChase = this.chaseBuilder + Optional<Chase<RW>> optChase = this.chaseBuilder .setRuleBase(this.strata.get(this.step_number)) .build(); if (optChase.isPresent()) { @@ -93,8 +97,8 @@ public class StratifiedChase implements Chase { } @Override - public FactBase getFactBase() { - return this.fb; + public ChasableData<RW> getChasableData() { + return this.chasableData; } @Override @@ -125,7 +129,7 @@ public class StratifiedChase implements Chase { @Override public String toString() { return "Steps : " + this.step_number + - "\nFacts :\n" +this.fb.toString(); + "\nFacts :\n" +this.chasableData.getWritingTarget().toString(); } private void initAll() { diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChaseBuilder.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChaseBuilder.java index eab5c207debbfa10d26338f223db081750de71de..bfebabc27962830d24c6d2533927d70332fb2da3 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChaseBuilder.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/metachase/stratified/StratifiedChaseBuilder.java @@ -2,6 +2,7 @@ package fr.boreal.forward_chaining.chase.metachase.stratified; import fr.boreal.forward_chaining.chase.Chase; import fr.boreal.forward_chaining.chase.ChaseBuilder; +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.halting_condition.HaltingCondition; import fr.boreal.forward_chaining.chase.halting_condition.LimitNumberOfStep; import fr.boreal.forward_chaining.chase.treatment.Debug; @@ -10,7 +11,9 @@ import fr.boreal.forward_chaining.chase.treatment.PredicateFilterEndTreatment; import fr.boreal.forward_chaining.chase.treatment.Pretreatment; import fr.boreal.grd.api.GraphOfFORuleDependencies; import fr.boreal.grd.impl.GRDImpl; -import fr.boreal.model.kb.api.FactBase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.RuleBase; import fr.boreal.model.logicalElements.api.Predicate; @@ -21,17 +24,17 @@ import java.util.stream.Collectors; * Builder for creating a StratifiedChase. * Allows setting various configurations and choosing different stratification methods. */ -public class StratifiedChaseBuilder { +public class StratifiedChaseBuilder<RW extends MaterializedData & Writable> { - private ChaseBuilder chaseBuilder; - private FactBase fb; + private ChaseBuilder<RW> chaseBuilder; + private ChasableData<RW> chasableData; private RuleBase rb; private List<RuleBase> strata = new ArrayList<>(); - private final Collection<HaltingCondition> haltingConditions = new ArrayList<>(); - private final Collection<Pretreatment> globalPretreatments = new ArrayList<>(); - private final Collection<Pretreatment> stepPretreatments = new ArrayList<>(); - private final Collection<EndTreatment> globalEndTreatments = new ArrayList<>(); - private final Collection<EndTreatment> endOfStepTreatments = new ArrayList<>(); + private final Collection<HaltingCondition<RW>> haltingConditions = new ArrayList<>(); + private final Collection<Pretreatment<RW>> globalPretreatments = new ArrayList<>(); + private final Collection<Pretreatment<RW>> stepPretreatments = new ArrayList<>(); + private final Collection<EndTreatment<RW>> globalEndTreatments = new ArrayList<>(); + private final Collection<EndTreatment<RW>> endOfStepTreatments = new ArrayList<>(); private boolean debug = false; private StratificationMethod stratificationMethod = StratificationMethod.NONE; private List<Predicate> finalPredicates; @@ -48,7 +51,7 @@ public class StratifiedChaseBuilder { * * @param chaseBuilder the ChaseBuilder instance to use. */ - public StratifiedChaseBuilder(ChaseBuilder chaseBuilder) { + public StratifiedChaseBuilder(ChaseBuilder<RW> chaseBuilder) { this.chaseBuilder = chaseBuilder; } @@ -59,9 +62,10 @@ public class StratifiedChaseBuilder { * @param rb the RuleBase. * @return the default StratifiedChaseBuilder initialized with the given parameters. */ - public static StratifiedChaseBuilder defaultBuilder(FactBase fb, RuleBase rb) { - return new StratifiedChaseBuilder(new ChaseBuilder()) - .setFactBase(fb) + public static <RW extends MaterializedData & Writable> + StratifiedChaseBuilder<RW> defaultBuilder(ChasableData<RW> fb, RuleBase rb) { + return new StratifiedChaseBuilder<RW>(new ChaseBuilder<>()) + .setChasableData(fb) .setRuleBase(rb); } @@ -71,7 +75,8 @@ public class StratifiedChaseBuilder { * @param chaseBuilder the ChaseBuilder instance to use. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder setChaseBuilder(ChaseBuilder chaseBuilder) { + public StratifiedChaseBuilder<RW> setChaseBuilder( + ChaseBuilder<RW> chaseBuilder) { this.chaseBuilder = chaseBuilder; return this; } @@ -79,11 +84,11 @@ public class StratifiedChaseBuilder { /** * Sets the FactBase. * - * @param fb the FactBase. + * @param chasableData the chasable data. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder setFactBase(FactBase fb) { - this.fb = fb; + public StratifiedChaseBuilder<RW> setChasableData(ChasableData<RW> chasableData) { + this.chasableData = chasableData; return this; } @@ -93,7 +98,7 @@ public class StratifiedChaseBuilder { * @param rb the RuleBase. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder setRuleBase(RuleBase rb) { + public StratifiedChaseBuilder<RW> setRuleBase(RuleBase rb) { this.rb = rb; return this; } @@ -105,7 +110,7 @@ public class StratifiedChaseBuilder { * @param strata the list of RuleBase. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder setStrata(List<RuleBase> strata) { + public StratifiedChaseBuilder<RW> setStrata(List<RuleBase> strata) { this.strata = strata; this.stratificationMethod = StratificationMethod.NONE; return this; @@ -117,7 +122,7 @@ public class StratifiedChaseBuilder { * * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder usePseudoMinimalStratification() { + public StratifiedChaseBuilder<RW> usePseudoMinimalStratification() { this.stratificationMethod = StratificationMethod.PSEUDO_MINIMAL; return this; } @@ -128,7 +133,7 @@ public class StratifiedChaseBuilder { * * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder useStratification() { + public StratifiedChaseBuilder<RW> useStratification() { this.stratificationMethod = StratificationMethod.DEFAULT; return this; } @@ -139,7 +144,7 @@ public class StratifiedChaseBuilder { * * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder useSingleEvaluationStratification() { + public StratifiedChaseBuilder<RW> useSingleEvaluationStratification() { this.stratificationMethod = StratificationMethod.SINGLE_EVALUATION; return this; } @@ -150,7 +155,9 @@ public class StratifiedChaseBuilder { * @param conditions the halting conditions to add. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder addHaltingConditions(HaltingCondition... conditions) { + @SafeVarargs + public final StratifiedChaseBuilder<RW> + addHaltingConditions(HaltingCondition<RW>... conditions) { this.haltingConditions.addAll(Arrays.asList(conditions)); return this; } @@ -161,7 +168,8 @@ public class StratifiedChaseBuilder { * @param treatments the global pretreatments to add. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder addGlobalPretreatments(Pretreatment... treatments) { + @SafeVarargs + public final StratifiedChaseBuilder<RW> addGlobalPretreatments(Pretreatment<RW>... treatments) { this.globalPretreatments.addAll(Arrays.asList(treatments)); return this; } @@ -172,7 +180,8 @@ public class StratifiedChaseBuilder { * @param treatments the step pretreatments to add. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder addStepPretreatments(Pretreatment... treatments) { + @SafeVarargs + public final StratifiedChaseBuilder<RW> addStepPretreatments(Pretreatment<RW>... treatments) { this.stepPretreatments.addAll(Arrays.asList(treatments)); return this; } @@ -183,7 +192,8 @@ public class StratifiedChaseBuilder { * @param treatments the global end treatments to add. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder addGlobalEndTreatments(EndTreatment... treatments) { + @SafeVarargs + public final StratifiedChaseBuilder<RW> addGlobalEndTreatments(EndTreatment<RW>... treatments) { this.globalEndTreatments.addAll(Arrays.asList(treatments)); return this; } @@ -194,7 +204,8 @@ public class StratifiedChaseBuilder { * @param treatments the end of step treatments to add. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder addEndOfStepTreatments(EndTreatment... treatments) { + @SafeVarargs + public final StratifiedChaseBuilder<RW> addEndOfStepTreatments(EndTreatment<RW>... treatments) { this.endOfStepTreatments.addAll(Arrays.asList(treatments)); return this; } @@ -205,7 +216,7 @@ public class StratifiedChaseBuilder { * @param predicates the list of predicates to keep. * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder setFinalPredicates(List<Predicate> predicates) { + public StratifiedChaseBuilder<RW> setFinalPredicates(List<Predicate> predicates) { this.finalPredicates = predicates; return this; } @@ -215,7 +226,7 @@ public class StratifiedChaseBuilder { * * @return this StratifiedChaseBuilder instance. */ - public StratifiedChaseBuilder debug() { + public StratifiedChaseBuilder<RW> debug() { this.debug = true; return this; } @@ -225,12 +236,12 @@ public class StratifiedChaseBuilder { * * @return an Optional containing the StratifiedChase if successfully built, otherwise an empty Optional. */ - public Optional<Chase> build() { + public Optional<Chase<RW>> build() { if (chaseBuilder == null) { - chaseBuilder = new ChaseBuilder(); + chaseBuilder = new ChaseBuilder<>(); } - if (fb == null) { + if (chasableData == null) { return Optional.empty(); } @@ -238,7 +249,7 @@ public class StratifiedChaseBuilder { return Optional.empty(); } - chaseBuilder.setFactBase(fb); + chaseBuilder.setChasableData(chasableData); // Apply the selected stratification method if (strata.isEmpty()) { @@ -259,7 +270,7 @@ public class StratifiedChaseBuilder { case SINGLE_EVALUATION: strata = grd.getSingleEvaluationStratification() .orElseThrow(() -> new IllegalArgumentException("The rule base must be stratifiable")); - this.chaseBuilder.addHaltingConditions(new LimitNumberOfStep(1)); + this.chaseBuilder.addHaltingConditions(new LimitNumberOfStep<RW>(1)); break; case NONE: break; @@ -276,9 +287,9 @@ public class StratifiedChaseBuilder { this.addEndOfStepTreatments(new Debug()); } - return Optional.of(new StratifiedChase( + return Optional.of(new StratifiedChase<>( chaseBuilder, - fb, + chasableData, strata, haltingConditions, globalPretreatments, diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/AbstractRuleApplier.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/AbstractRuleApplier.java index ba1f76e05f53746f6905105a2fbe4ab476b912e0..b97b466121d345f7c657d143d44d44de566cf461 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/AbstractRuleApplier.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/AbstractRuleApplier.java @@ -5,6 +5,8 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import org.slf4j.Logger; import fr.boreal.forward_chaining.chase.Chase; @@ -20,7 +22,7 @@ import fr.boreal.model.rule.api.FORule; * * Abstract class */ -public abstract class AbstractRuleApplier implements RuleApplier { +public abstract class AbstractRuleApplier<RW extends MaterializedData & Writable> implements RuleApplier<RW> { protected Logger LOG; @@ -32,17 +34,17 @@ public abstract class AbstractRuleApplier implements RuleApplier { /** * How to evaluate the rule's body */ - protected final TriggerComputer computer; + protected final TriggerComputer<RW> computer; /** * How to check the trigger should be applied */ - protected final TriggerChecker checker; + protected final TriggerChecker<RW> checker; /** * How to effectively apply the trigger */ - protected final TriggerApplier applier; + protected final TriggerApplier<RW> applier; /** * Constructor @@ -52,7 +54,11 @@ public abstract class AbstractRuleApplier implements RuleApplier { * @param checker the TriggerChecker * @param applier the TriggerApplier */ - public AbstractRuleApplier(BodyToQueryTransformer transformer, TriggerComputer computer, TriggerChecker checker, TriggerApplier applier) { + public AbstractRuleApplier( + BodyToQueryTransformer transformer, + TriggerComputer<RW> computer, + TriggerChecker<RW> checker, + TriggerApplier<RW> applier) { this.transformer = transformer; this.computer = computer; this.checker = checker; @@ -60,7 +66,7 @@ public abstract class AbstractRuleApplier implements RuleApplier { } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.computer.init(c); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/BreadthFirstTriggerRuleApplier.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/BreadthFirstTriggerRuleApplier.java index 97d7b8f6153b3f8f38903aab5ef162c36527ab80..3c970667cd896be091fd8cad377639bc14933e33 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/BreadthFirstTriggerRuleApplier.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/BreadthFirstTriggerRuleApplier.java @@ -1,10 +1,13 @@ package fr.boreal.forward_chaining.chase.rule_applier; import fr.boreal.forward_chaining.chase.RuleApplicationStepResult; +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.rule_applier.body_to_query_transformer.BodyToQueryTransformer; import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.TriggerApplier; import fr.boreal.forward_chaining.chase.rule_applier.trigger_checker.TriggerChecker; import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.TriggerComputer; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; @@ -22,7 +25,7 @@ import java.util.*; * * Applying the homomorphism to the head of the rule and * * Adding the resulting atoms to the factbase */ -public class BreadthFirstTriggerRuleApplier extends AbstractRuleApplier { +public class BreadthFirstTriggerRuleApplier<RW extends MaterializedData & Writable> extends AbstractRuleApplier<RW> { /** * Constructor @@ -32,13 +35,17 @@ public class BreadthFirstTriggerRuleApplier extends AbstractRuleApplier { * @param checker the TriggerChecker * @param applier the TriggerApplier */ - public BreadthFirstTriggerRuleApplier(BodyToQueryTransformer transformer, TriggerComputer computer, TriggerChecker checker, TriggerApplier applier) { + public BreadthFirstTriggerRuleApplier( + BodyToQueryTransformer transformer, + TriggerComputer<RW> computer, + TriggerChecker<RW> checker, + TriggerApplier<RW> applier) { super(transformer, computer, checker, applier); LOG = LoggerFactory.getLogger(BreadthFirstTriggerRuleApplier.class); } @Override - public RuleApplicationStepResult apply(Collection<FORule> rules, FactBase fb) { + public RuleApplicationStepResult apply(Collection<FORule> rules, ChasableData<RW> chasableData) { Map<FOQuery<?>, Collection<FORule>> rules_by_body = this.groupRulesByBodyQuery(rules); Map<FOQuery<?>, Collection<Substitution>> substitutions_by_body = new HashMap<>(); @@ -46,7 +53,7 @@ public class BreadthFirstTriggerRuleApplier extends AbstractRuleApplier { for(FOQuery<?> body : rules_by_body.keySet()) { Iterator<Substitution> res; try { - res = this.computer.compute(body, fb); + res = this.computer.compute(body, chasableData); substitutions_by_body.put(body, new HashSet<>()); while(res.hasNext()) { substitutions_by_body.get(body).add(res.next()); @@ -68,7 +75,7 @@ public class BreadthFirstTriggerRuleApplier extends AbstractRuleApplier { for (FORule rule : rules_by_body.get(body)) { boolean toApply; try { - toApply = this.checker.check(rule, substitution, fb); + toApply = this.checker.check(rule, substitution, chasableData.getWritingTarget()); } catch (Exception e) { throw new RuntimeException( String.format("[%s::apply] Error during the application of the rules - " + @@ -81,7 +88,7 @@ public class BreadthFirstTriggerRuleApplier extends AbstractRuleApplier { FOFormula application_facts; try { - application_facts = this.applier.apply(rule, substitution, fb); + application_facts = this.applier.apply(rule, substitution, chasableData.getWritingTarget()); } catch (Exception e) { Thread.currentThread().interrupt(); throw new RuntimeException( diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/MultiThreadRuleApplier.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/MultiThreadRuleApplier.java index 4ce24d74bb5297161c3a844ba0431de9232723ec..298a6e45b0b5e6c88f5fb5f37264a96bb633aa5c 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/MultiThreadRuleApplier.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/MultiThreadRuleApplier.java @@ -1,10 +1,13 @@ package fr.boreal.forward_chaining.chase.rule_applier; import fr.boreal.forward_chaining.chase.RuleApplicationStepResult; +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.rule_applier.body_to_query_transformer.BodyToQueryTransformer; import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.TriggerApplier; import fr.boreal.forward_chaining.chase.rule_applier.trigger_checker.TriggerChecker; import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.TriggerComputer; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; @@ -20,7 +23,7 @@ import java.util.concurrent.*; * Multithreaded Rule Applier with a worker for each rule. * @author Guillaume Pérution-Kihli */ -public class MultiThreadRuleApplier extends AbstractRuleApplier { +public class MultiThreadRuleApplier<RW extends MaterializedData & Writable> extends AbstractRuleApplier<RW> { private Map<FORule, BlockingQueue<Substitution>> checkingQueues; // Queues for checking per rule private Map<FORule, BlockingQueue<Substitution>> applicationQueues; // Queues for application per rule @@ -28,12 +31,16 @@ public class MultiThreadRuleApplier extends AbstractRuleApplier { private Map<FORule, Boolean> checkingFinished; // Track when each checking process has finished for each rule private static final int MAX_WORKERS = 32; - public MultiThreadRuleApplier(BodyToQueryTransformer transformer, TriggerComputer computer, TriggerChecker checker, TriggerApplier applier) { + public MultiThreadRuleApplier( + BodyToQueryTransformer transformer, + TriggerComputer<RW> computer, + TriggerChecker<RW> checker, + TriggerApplier<RW> applier) { super(transformer, computer, checker, applier); } @Override - public RuleApplicationStepResult apply(Collection<FORule> rules, FactBase fb) { + public RuleApplicationStepResult apply(Collection<FORule> rules, ChasableData<RW> chasableData) { ExecutorService producerExecutor = Executors.newCachedThreadPool(); // 1 thread per body // Pool for checking ExecutorService checkingWorkerExecutor = Executors.newFixedThreadPool(Math.min(MAX_WORKERS, rules.size())); // Pool for checking per rule @@ -62,13 +69,13 @@ public class MultiThreadRuleApplier extends AbstractRuleApplier { // Start producers: 1 thread per body (FOQuery) for (FOQuery<?> body : rulesByBody.keySet()) { - producerExecutor.submit(() -> processBody(body, fb, rulesByBody.get(body))); + producerExecutor.submit(() -> processBody(body, chasableData, rulesByBody.get(body))); } // Start worker threads for checking and application for each rule for (FORule rule : rules) { - checkingWorkerExecutor.submit(() -> processChecking(fb, rule)); - applicationWorkerExecutor.submit(() -> processApplication(fb, createdFacts, appliedRules, rule)); + checkingWorkerExecutor.submit(() -> processChecking(chasableData, rule)); + applicationWorkerExecutor.submit(() -> processApplication(chasableData, createdFacts, appliedRules, rule)); } // Shutdown the checking and application worker executors @@ -84,9 +91,9 @@ public class MultiThreadRuleApplier extends AbstractRuleApplier { * Producer thread: Computes the substitutions (homomorphisms) for a given body (FOQuery) * and enqueues operations to the checking queue of each rule. */ - private void processBody(FOQuery<?> body, FactBase fb, Collection<FORule> associatedRules) { + private void processBody(FOQuery<?> body, ChasableData<RW> chasableData, Collection<FORule> associatedRules) { try { - Iterator<Substitution> substitutions = this.computer.compute(body, fb); + Iterator<Substitution> substitutions = this.computer.compute(body, chasableData); substitutions.forEachRemaining(substitution -> { for (FORule rule : associatedRules) { try { @@ -114,7 +121,7 @@ public class MultiThreadRuleApplier extends AbstractRuleApplier { /** * Process checking of rules. */ - private void processChecking(FactBase fb, FORule rule) { + private void processChecking(ChasableData<RW> chasableData, FORule rule) { BlockingQueue<Substitution> queue = checkingQueues.get(rule); // Get the queue for this rule Substitution homomorphism = null; while (true) { @@ -130,7 +137,7 @@ public class MultiThreadRuleApplier extends AbstractRuleApplier { } // Perform the checking operation - if (this.checker.check(rule, homomorphism, fb)) { + if (this.checker.check(rule, homomorphism, chasableData.getWritingTarget())) { applicationQueues.get(rule).put(homomorphism); // Enqueue application task } @@ -148,7 +155,7 @@ public class MultiThreadRuleApplier extends AbstractRuleApplier { /** * Process application of facts. */ - private void processApplication(FactBase fb, Set<Atom> createdFacts, Set<FORule> appliedRules, FORule rule) { + private void processApplication(ChasableData<RW> chasableData, Set<Atom> createdFacts, Set<FORule> appliedRules, FORule rule) { BlockingQueue<Substitution> queue = applicationQueues.get(rule); // Get the queue for this rule Substitution homomorphism = null; while (true) { @@ -165,7 +172,7 @@ public class MultiThreadRuleApplier extends AbstractRuleApplier { // Perform the application operation FOFormula applicationFacts; synchronized (this.applier) { - applicationFacts = this.applier.apply(rule, homomorphism, fb); + applicationFacts = this.applier.apply(rule, homomorphism, chasableData.getWritingTarget()); } if (applicationFacts != null) { createdFacts.addAll(applicationFacts.asAtomSet()); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/ParallelTriggerRuleApplier.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/ParallelTriggerRuleApplier.java index af92f4158c9997d529e9e3dfaf819349640eb7d3..11540bb9f860588ecfe2c10304291e558045fe20 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/ParallelTriggerRuleApplier.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/ParallelTriggerRuleApplier.java @@ -6,10 +6,13 @@ import java.util.Iterator; import java.util.Map; import fr.boreal.forward_chaining.chase.RuleApplicationStepResult; +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.rule_applier.body_to_query_transformer.BodyToQueryTransformer; import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.TriggerApplier; import fr.boreal.forward_chaining.chase.rule_applier.trigger_checker.TriggerChecker; import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.TriggerComputer; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; @@ -24,7 +27,7 @@ import fr.boreal.model.rule.api.FORule; * * Applying the homomorphism to the head of the rule and * * Adding the resulting atoms to a temporary factbase that will need to be merged into the factbase at the end of the step */ -public class ParallelTriggerRuleApplier extends AbstractRuleApplier { +public class ParallelTriggerRuleApplier<RW extends MaterializedData & Writable> extends AbstractRuleApplier<RW> { /** * Constructor @@ -34,12 +37,16 @@ public class ParallelTriggerRuleApplier extends AbstractRuleApplier { * @param checker the TriggerChecker * @param applier the TriggerApplier */ - public ParallelTriggerRuleApplier(BodyToQueryTransformer transformer, TriggerComputer computer, TriggerChecker checker, TriggerApplier applier) { + public ParallelTriggerRuleApplier( + BodyToQueryTransformer transformer, + TriggerComputer<RW> computer, + TriggerChecker<RW> checker, + TriggerApplier<RW> applier) { super(transformer, computer, checker, applier); } @Override - public RuleApplicationStepResult apply(Collection<FORule> rules, FactBase fb) { + public RuleApplicationStepResult apply(Collection<FORule> rules, ChasableData<RW> chasableData) { Map<FOQuery<?>, Collection<FORule>> rules_by_body = this.groupRulesByBodyQuery(rules); Collection<FORule> applied_rules = new HashSet<>(); Collection<Atom> created_facts = new HashSet<>(); @@ -48,7 +55,7 @@ public class ParallelTriggerRuleApplier extends AbstractRuleApplier { for(FOQuery<?> body : rules_by_body.keySet()) { Iterator<Substitution> res; try { - res = this.computer.compute(body, fb); + res = this.computer.compute(body, chasableData); } catch (Exception e) { throw new RuntimeException( String.format("[%s::apply] Error during the application of the rules - " + @@ -74,7 +81,7 @@ public class ParallelTriggerRuleApplier extends AbstractRuleApplier { for(FORule rule : rules_by_body.get(body)) { boolean toApply; try { - toApply = this.checker.check(rule, h, fb); + toApply = this.checker.check(rule, h, chasableData.getWritingTarget()); } catch (Exception e) { throw new RuntimeException( String.format("[%s::apply] Error during the application of the rules - " + @@ -87,7 +94,7 @@ public class ParallelTriggerRuleApplier extends AbstractRuleApplier { FOFormula application_facts; try { - application_facts = this.applier.apply(rule, h, fb); + application_facts = this.applier.apply(rule, h, chasableData.getWritingTarget()); } catch (Exception e) { Thread.currentThread().interrupt(); throw new RuntimeException( diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/RuleApplier.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/RuleApplier.java index bcdee302cd05429d751c81845df35f6dac9ec2f1..e3f54cbdd454005a359fad0292f597b7524881fb 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/RuleApplier.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/RuleApplier.java @@ -4,26 +4,30 @@ import java.util.Collection; import fr.boreal.forward_chaining.chase.Chase; import fr.boreal.forward_chaining.chase.RuleApplicationStepResult; +import fr.boreal.forward_chaining.chase.data.ChasableData; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.rule.api.FORule; /** * A rule applier applies the given rules of the given factbase */ -public interface RuleApplier { +public interface RuleApplier<RW extends MaterializedData & Writable> { /** * Initialize the rule applier for the given chase * @param c the chase object */ - void init(Chase c); + void init(Chase<RW> c); /** - * Applies the given rules on the given factbase an returns the result (see {@link RuleApplicationStepResult}) + * Applies the given rules on the given data and returns the result (see {@link RuleApplicationStepResult}) * @param rules the rules to apply - * @param fb the factbase to apply the rules on + * @param chasableData the data to apply the rules on * @return the result of one application step */ - RuleApplicationStepResult apply(Collection<FORule> rules, FactBase fb); + RuleApplicationStepResult apply(Collection<FORule> rules, ChasableData<RW> chasableData); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/SourceDelegatedDatalogRuleApplier.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/SourceDelegatedDatalogRuleApplier.java index 40584c6dce1e36b03cbb36612d77864a63566d2a..1372aa63c5ac27c88befafd20f4cb7476466c6cb 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/SourceDelegatedDatalogRuleApplier.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/SourceDelegatedDatalogRuleApplier.java @@ -2,6 +2,7 @@ package fr.boreal.forward_chaining.chase.rule_applier; import fr.boreal.forward_chaining.chase.Chase; import fr.boreal.forward_chaining.chase.RuleApplicationStepResult; +import fr.boreal.forward_chaining.chase.data.ChasableData; import fr.boreal.forward_chaining.chase.rule_applier.body_to_query_transformer.AllTransformer; import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.TriggerApplierImpl; import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_handler.DirectApplication; @@ -9,6 +10,8 @@ import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.renamer.Fre import fr.boreal.forward_chaining.chase.rule_applier.trigger_checker.ObliviousChecker; import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.NaiveTriggerComputer; import fr.boreal.model.data.readable.DatalogDelegable; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; @@ -24,21 +27,21 @@ import java.util.HashSet; * * Delegating the application to the factbase if it can handle it * * Using a fallback method is it can't */ -public class SourceDelegatedDatalogRuleApplier implements RuleApplier { +public class SourceDelegatedDatalogRuleApplier<RW extends MaterializedData & Writable> implements RuleApplier<RW> { - private final RuleApplier fallback; + private final RuleApplier<RW> fallback; /** * DEfault constructor with a oblivious/naive chase as fallback */ public SourceDelegatedDatalogRuleApplier() { - this(new BreadthFirstTriggerRuleApplier( + this(new BreadthFirstTriggerRuleApplier<>( new AllTransformer(), - new NaiveTriggerComputer(FOQueryEvaluatorWithDBMSDelegation.defaultInstance()), - new ObliviousChecker(), - new TriggerApplierImpl( + new NaiveTriggerComputer<>(FOQueryEvaluatorWithDBMSDelegation.defaultInstance()), + new ObliviousChecker<>(), + new TriggerApplierImpl<>( new FreshRenamer(SameObjectTermFactory.instance()), - new DirectApplication()) + new DirectApplication<>()) )); } @@ -46,19 +49,20 @@ public class SourceDelegatedDatalogRuleApplier implements RuleApplier { * Constructor with that applied the given chase as fallback * @param fallback fallback application */ - public SourceDelegatedDatalogRuleApplier(RuleApplier fallback) { + public SourceDelegatedDatalogRuleApplier(RuleApplier<RW> fallback) { this.fallback = fallback; } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { // nothing to do } @Override - public RuleApplicationStepResult apply(Collection<FORule> rules, FactBase fb) { - if(fb instanceof DatalogDelegable storage) { + public RuleApplicationStepResult apply(Collection<FORule> rules, ChasableData<RW> chasableData) { + if(chasableData.getWritingTarget() instanceof DatalogDelegable storage + && chasableData.getDataSource().isEmpty()) { // TODO: it would be better to check the vocabulary of the rule Collection<FORule> existential_rules = new HashSet<>(); Collection<FORule> range_restricted_rules = new HashSet<>(); @@ -74,10 +78,10 @@ public class SourceDelegatedDatalogRuleApplier implements RuleApplier { try { changed = storage.delegate(range_restricted_rules); } catch (Exception e) { - e.printStackTrace(); + throw new RuntimeException(e); } - RuleApplicationStepResult existential_result = this.fallback.apply(existential_rules, fb); + RuleApplicationStepResult existential_result = this.fallback.apply(existential_rules, chasableData); range_restricted_rules.addAll(existential_result.applied_rules()); Collection<Atom> facts = existential_result.created_facts(); @@ -92,7 +96,7 @@ public class SourceDelegatedDatalogRuleApplier implements RuleApplier { return new RuleApplicationStepResult(range_restricted_rules, facts); } } - return this.fallback.apply(rules, fb); + return this.fallback.apply(rules, chasableData); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplier.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplier.java index 8d324c0d04a706cc663b500c81b1a673d93b6f30..cf164f934eeb19e049ff5115f035ebb9f98dc94e 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplier.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplier.java @@ -1,5 +1,7 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_applier; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; @@ -8,15 +10,15 @@ import fr.boreal.model.rule.api.FORule; /** * A trigger applier applies an homomorphism to the rule's head and add the resulting atoms to the factbase */ -public interface TriggerApplier { +public interface TriggerApplier<RW extends MaterializedData & Writable> { /** * Applies the given substitution to the rule's head and add the result to the factbase * @param rule the rule to apply * @param substitution the trigger of the rule - * @param fb the factbase + * @param readWriteData Writable where to add the new facts * @return the effectively added facts */ - FOFormula apply(FORule rule, Substitution substitution, FactBase fb); + FOFormula apply(FORule rule, Substitution substitution, RW readWriteData); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplierImpl.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplierImpl.java index 2303e85b453f83ad9114f71b0c0717e6dab21607..06eadf8f6a2cf1629308a2239f9bb7364127c552 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplierImpl.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/TriggerApplierImpl.java @@ -2,6 +2,8 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_applier; import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_handler.FactsHandler; import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.renamer.TriggerRenamer; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.FOFormulas; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; @@ -13,7 +15,7 @@ import fr.boreal.model.rule.api.FORule; * image of the rule's head with the renamed homomorphism * then add the images * to the facts */ -public class TriggerApplierImpl implements TriggerApplier { +public class TriggerApplierImpl<RW extends MaterializedData & Writable> implements TriggerApplier<RW> { private final TriggerRenamer tr; private final FactsHandler fh; @@ -28,11 +30,11 @@ public class TriggerApplierImpl implements TriggerApplier { } @Override - public FOFormula apply(FORule rule, Substitution substitution, FactBase fb) { - Substitution full_substitution = this.tr.renameExitentials(rule, substitution); + public FOFormula apply(FORule rule, Substitution substitution, RW readWriteData) { + Substitution full_substitution = this.tr.renameExistentials(rule, substitution); boolean evaluateFunctions = true; FOFormula new_facts = FOFormulas.createImageWith(rule.getHead(), full_substitution, evaluateFunctions); - return this.fh.add(new_facts, fb); + return this.fh.add(new_facts, readWriteData); } } \ No newline at end of file diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DelegatedApplication.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DelegatedApplication.java index eae0a76333a76c45647a7b9d53779367a009c90a..af81b4af0697dab45a8978bd89a69bd75ba531ff 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DelegatedApplication.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DelegatedApplication.java @@ -3,6 +3,9 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_hand import java.util.Collection; import java.util.stream.Collectors; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.formula.factory.FOFormulaFactory; import fr.boreal.model.kb.api.FactBase; @@ -10,12 +13,13 @@ import fr.boreal.model.kb.api.FactBase; /** * Keep the new facts and delay the addition in the factbase */ -public class DelegatedApplication implements FactsHandler { +public class DelegatedApplication<RW extends MaterializedData & Writable> + implements FactsHandler<RW> { @Override - public FOFormula add(FOFormula new_facts, FactBase fb) { + public FOFormula add(FOFormula new_facts, RW readWriteData) { Collection<FOFormula> atoms_to_add = new_facts.asAtomSet().stream() - .filter(a -> !fb.contains(a)) + .filter(a -> !readWriteData.contains(a)) .collect(Collectors.toSet()); if(atoms_to_add.isEmpty()) { diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DirectApplication.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DirectApplication.java index 575da9a10cb164f9052b33ebe57aa0ffde8f7942..e99cc895f21328ff18a1c1bbc2e31769524a42cd 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DirectApplication.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/DirectApplication.java @@ -1,16 +1,18 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_handler; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; /** * Adds the created facts to the factbase */ -public class DirectApplication implements FactsHandler { +public class DirectApplication<RW extends MaterializedData & Writable> implements FactsHandler<RW> { @Override - public FOFormula add(FOFormula new_facts, FactBase fb) { - boolean added_something = fb.add(new_facts); + public FOFormula add(FOFormula new_facts, RW readWriteData) { + boolean added_something = readWriteData.add(new_facts); return added_something ? new_facts : null; } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/FactsHandler.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/FactsHandler.java index f18374ee717e11bf30a45ecc3b8db91782a4874d..34cb75d3e5fd9e70e0007eb5caf9f2e9c76d19ac 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/FactsHandler.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/facts_handler/FactsHandler.java @@ -1,19 +1,22 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_handler; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; /** * Handles newly created facts */ -public interface FactsHandler { +public interface FactsHandler<RW extends MaterializedData & Writable> { /** - * Adds the facts to the factbase + * Adds the facts to the QueryableWritableData * @param new_facts fatcs to add - * @param fb factbase + * @param readWriteData Writable where to add the new facts * @return the effectively added facts */ - FOFormula add(FOFormula new_facts, FactBase fb); + FOFormula add(FOFormula new_facts, RW readWriteData); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/BodySkolem.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/BodySkolem.java index 925d678fa283ed131083cb881cd06d5d4c06cfb7..a83371ef7d5d3a92df95c926e81be5858303f786 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/BodySkolem.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/BodySkolem.java @@ -27,7 +27,7 @@ public class BodySkolem implements TriggerRenamer { } @Override - public Substitution renameExitentials(FORule rule, final Substitution substitution) { + public Substitution renameExistentials(FORule rule, final Substitution substitution) { if (!existentials_names.containsKey(rule)) { existentials_names.put(rule, new HashMap<>()); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FreshRenamer.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FreshRenamer.java index 00f19c6f83858a3fda719d6d69e70092155d486e..b8b4d1780d5b3a2aeb4ee6eea54720f45938390c 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FreshRenamer.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FreshRenamer.java @@ -21,7 +21,7 @@ public class FreshRenamer implements TriggerRenamer { } @Override - public Substitution renameExitentials(FORule rule, final Substitution substitution) { + public Substitution renameExistentials(FORule rule, final Substitution substitution) { Substitution s = new SubstitutionImpl(); for(Variable v : rule.getExistentials()) { s.add(v, this.tf.createOrGetFreshVariable()); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierByPieceSkolem.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierByPieceSkolem.java index 024e1fa492ffc4254e9eae5b428f29d0256e3980..3fdb994103e89573c199c1e8422b200a0dcae180 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierByPieceSkolem.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierByPieceSkolem.java @@ -30,7 +30,7 @@ public class FrontierByPieceSkolem implements TriggerRenamer { } @Override - public Substitution renameExitentials(FORule rule, final Substitution substitution) { + public Substitution renameExistentials(FORule rule, final Substitution substitution) { if (!existentials_names.containsKey(rule)) { existentials_names.put(rule, new HashMap<>()); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierSkolem.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierSkolem.java index ed9642df36c1857878c49d47c1bce84276aca53f..34104c9e2d06aed195904ae959ba555907260d06 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierSkolem.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/FrontierSkolem.java @@ -27,7 +27,7 @@ public class FrontierSkolem implements TriggerRenamer { } @Override - public Substitution renameExitentials(FORule rule, final Substitution substitution) { + public Substitution renameExistentials(FORule rule, final Substitution substitution) { if (!existentials_names.containsKey(rule)) { existentials_names.put(rule, new HashMap<>()); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/TriggerRenamer.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/TriggerRenamer.java index 9a1194a2a32aac809ca3163fff93fa64d9e78ce0..6b3a58d613e33672950eabb85e34ece2ba4749fd 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/TriggerRenamer.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_applier/renamer/TriggerRenamer.java @@ -16,6 +16,6 @@ public interface TriggerRenamer { * and an additional entry for each existential of the rule * that is not in the initial substitution */ - Substitution renameExitentials(FORule rule, final Substitution substitution); + Substitution renameExistentials(FORule rule, final Substitution substitution); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/AlwaysTrueChecker.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/AlwaysTrueChecker.java index 3de0a8dba0a4074f0cd15cc5501d487ffb3739e3..f9cfb5db8273fb2edab75e4c9293118dc883dd43 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/AlwaysTrueChecker.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/AlwaysTrueChecker.java @@ -1,5 +1,7 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_checker; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.rule.api.FORule; @@ -8,10 +10,10 @@ import fr.boreal.model.rule.api.FORule; * Always accept the given trigger * For test purposes or when you are sure the trigger is new */ -public class AlwaysTrueChecker implements TriggerChecker { +public class AlwaysTrueChecker<RW extends MaterializedData & Writable> implements TriggerChecker<RW> { @Override - public boolean check(FORule rule, Substitution substitution, FactBase fb) { + public boolean check(FORule rule, Substitution substitution, RW readWriteData) { return true; } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/EquivalentChecker.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/EquivalentChecker.java index 0b6866bdce6f27ad9b0902f49a62283e150df68d..25de3465f08332b296f71fdf5da363ae4834a37d 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/EquivalentChecker.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/EquivalentChecker.java @@ -6,7 +6,9 @@ import java.util.Iterator; import java.util.Set; import java.util.stream.Collectors; +import fr.boreal.model.data.readable.MaterializedData; import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.FOFormulas; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.formula.api.FOFormulaConjunction; @@ -24,9 +26,9 @@ import fr.boreal.query_evaluation.generic.GenericFOQueryEvaluator; /** * Checks if the factbase created with the given trigger would be equivalent to the current factbase */ -public class EquivalentChecker implements TriggerChecker { +public class EquivalentChecker<RW extends MaterializedData & Writable> implements TriggerChecker<RW> { - private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; + private final FOQueryEvaluator<FOFormula, ? super RW> evaluator; /** * Default constructor using the generic query evaluator @@ -39,25 +41,25 @@ public class EquivalentChecker implements TriggerChecker { * Constructor using the given query evaluator * @param evaluator the query evaluator to use */ - public EquivalentChecker(FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public EquivalentChecker(FOQueryEvaluator<FOFormula, ? super RW> evaluator) { this.evaluator = evaluator; } @Override - public boolean check(FORule rule, Substitution substitution, FactBase fb) { - FOFormulaConjunction piece = getPiecesInFactBase(rule, substitution, fb); + public boolean check(FORule rule, Substitution substitution, RW readWriteData) { + FOFormulaConjunction piece = getPiecesInFactBase(rule, substitution, readWriteData); FOFormulaConjunction complete_formula = FOFormulaFactory.instance().createOrGetConjunction( piece, FOFormulas.createImageWith(rule.getHead(), substitution)); FOQuery<FOFormulaConjunction> query = FOQueryFactory.instance().createOrGetQuery(complete_formula, null, null); try { - return !this.evaluator.existHomomorphism(query, fb); + return !this.evaluator.existHomomorphism(query, readWriteData); } catch (EvaluationException e) { throw new RuntimeException(e); } } - private FOFormulaConjunction getPiecesInFactBase(FORule r, Substitution h, FactBase factBase) { + private FOFormulaConjunction getPiecesInFactBase(FORule r, Substitution h, RW readWriteData) { Collection<Variable> vars = FOFormulas.createImageWith(r.getBody(), h).getVariables().collect(Collectors.toSet()); Set<Variable> addedVars = new HashSet<>(); @@ -68,7 +70,7 @@ public class EquivalentChecker implements TriggerChecker { vars.remove(v); addedVars.add(v); - Iterator<Atom> it = factBase.getAtomsByTerm(v).iterator(); + Iterator<Atom> it = readWriteData.getAtomsByTerm(v).iterator(); while (it.hasNext()) { Atom a = it.next(); result.add(a); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/MultiTriggerChecker.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/MultiTriggerChecker.java index 0878661d9245defdad2410bcadbffb498dece35e..9f2af4fdd81ebf8a3b94423e6ba52c2e9b8b1b71 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/MultiTriggerChecker.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/MultiTriggerChecker.java @@ -3,6 +3,8 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_checker; import java.util.Arrays; import java.util.Collection; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.rule.api.FORule; @@ -10,27 +12,27 @@ import fr.boreal.model.rule.api.FORule; /** * Combines multiple checkers and checks that all of them accept the given trigger */ -public class MultiTriggerChecker implements TriggerChecker { +public class MultiTriggerChecker<RW extends MaterializedData & Writable> implements TriggerChecker<RW> { - final Collection<TriggerChecker> checkers; + final Collection<TriggerChecker<RW>> checkers; /** * @param checkers all the criteria to check */ - public MultiTriggerChecker (TriggerChecker... checkers) { + public MultiTriggerChecker (TriggerChecker<RW>... checkers) { this.checkers = Arrays.asList(checkers); } /** * @param checkers all the criteria to check */ - public MultiTriggerChecker (Collection<TriggerChecker> checkers) { + public MultiTriggerChecker (Collection<TriggerChecker<RW>> checkers) { this.checkers = checkers; } @Override - public boolean check(FORule rule, Substitution substitution, FactBase fb) { - return this.checkers.stream().allMatch(checker -> checker.check(rule, substitution, fb)); + public boolean check(FORule rule, Substitution substitution, RW readWriteData) { + return this.checkers.stream().allMatch(checker -> checker.check(rule, substitution, readWriteData)); } } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/ObliviousChecker.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/ObliviousChecker.java index 4293e7cc87582e73714ce583e6cee1bbd31f390e..157ca7cde0f5e609544009241aff58e1f85c143b 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/ObliviousChecker.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/ObliviousChecker.java @@ -5,6 +5,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.rule.api.FORule; @@ -13,12 +15,12 @@ import fr.boreal.model.rule.api.FORule; * Accept the given trigger if it is the first time. * This is the criteria for the oblivious chase */ -public class ObliviousChecker implements TriggerChecker { +public class ObliviousChecker<RW extends MaterializedData & Writable> implements TriggerChecker<RW> { final Map<FORule, Set<Substitution>> alreadyTreated = new HashMap<>(); @Override - public boolean check(FORule rule, Substitution substitution, FactBase fb) { + public boolean check(FORule rule, Substitution substitution, RW readWriteData) { Set<Substitution> rule_substitutions = this.alreadyTreated.get(rule); if(rule_substitutions == null) { rule_substitutions = new HashSet<>(); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/RestrictedChecker.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/RestrictedChecker.java index a840f8b82f23e74ba3ee1161deccc97f6186b3cd..d86fbb46007593f64ed027c784242b304f6590c9 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/RestrictedChecker.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/RestrictedChecker.java @@ -1,6 +1,8 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_checker; +import fr.boreal.model.data.readable.MaterializedData; import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; @@ -16,9 +18,9 @@ import java.util.Set; * Accept the trigger if it cannot be extended with the head of the rule * This is the criteria for the restricted chase */ -public class RestrictedChecker implements TriggerChecker { +public class RestrictedChecker<RW extends MaterializedData & Writable> implements TriggerChecker<RW> { - private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; + private final FOQueryEvaluator<FOFormula, ? super RW> evaluator; /** * Default constructor using the generic query evaluator @@ -31,15 +33,15 @@ public class RestrictedChecker implements TriggerChecker { * Constructor using the given query evaluator * @param evaluator the query evaluator to use */ - public RestrictedChecker(FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public RestrictedChecker(FOQueryEvaluator<FOFormula, ? super RW> evaluator) { this.evaluator = evaluator; } @Override - public boolean check(FORule rule, Substitution substitution, FactBase fb) { + public boolean check(FORule rule, Substitution substitution, RW readWriteData) { FOQuery<FOFormula> query = FOQueryFactory.instance().createOrGetQuery(rule.getHead(), Set.of()); try { - return !this.evaluator.existHomomorphism(query, fb, substitution); + return !this.evaluator.existHomomorphism(query, readWriteData, substitution); } catch (EvaluationException e) { throw new RuntimeException(e); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/SemiObliviousChecker.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/SemiObliviousChecker.java index 5aab4bb1074c11d9ccf2def9dbd71d07661f8b25..c3683f352d63766152895a5344005fd9c63735f7 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/SemiObliviousChecker.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/SemiObliviousChecker.java @@ -5,6 +5,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.rule.api.FORule; @@ -13,12 +15,12 @@ import fr.boreal.model.rule.api.FORule; * Accept the trigger if it is the first time, checking only the variables from the frontier of the rule. * This is the criteria for the semi-oblivious chase */ -public class SemiObliviousChecker implements TriggerChecker { +public class SemiObliviousChecker<RW extends MaterializedData & Writable> implements TriggerChecker<RW> { final Map<FORule, Set<Substitution>> alreadyTreated = new HashMap<>(); @Override - public boolean check(FORule rule, Substitution substitution, FactBase fb) { + public boolean check(FORule rule, Substitution substitution, RW readWriteData) { Substitution frontier_limited = substitution.limitedTo(rule.getFrontier()); Set<Substitution> rule_substitutions = this.alreadyTreated.get(rule); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/TriggerChecker.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/TriggerChecker.java index 7ca56943ec3671589dfae59eefab33bc04fe9154..4c1fa694a436b1c8a29fa5b78dce7d1caed63fb6 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/TriggerChecker.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_checker/TriggerChecker.java @@ -1,20 +1,22 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_checker; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.rule.api.FORule; /** - * Checks if the given trigger respect a criteria + * Checks if the given trigger respects a criteria */ -public interface TriggerChecker { +public interface TriggerChecker<RW extends MaterializedData & Writable> { /** * @param rule the rule that is triggered * @param substitution the trigger - * @param fb the factbase - * @return true iff the trigger respect the criteria + * @param readWriteData Writable where to add the new facts + * @return true iff the trigger respects the criteria */ - boolean check(FORule rule, Substitution substitution, FactBase fb); + boolean check(FORule rule, Substitution substitution, RW readWriteData); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/NaiveTriggerComputer.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/NaiveTriggerComputer.java index a3167098b70ccf8e76bff441e645edec80663727..1bfccb794dbede1a4c63fd4a1166525081d493d0 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/NaiveTriggerComputer.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/NaiveTriggerComputer.java @@ -3,7 +3,11 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_computer; import java.util.Iterator; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.forward_chaining.chase.data.ChasableData; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; @@ -14,9 +18,9 @@ import fr.boreal.query_evaluation.generic.GenericFOQueryEvaluator; /** * This computing method consist of only evaluating the rule's body on the factbase. */ -public class NaiveTriggerComputer implements TriggerComputer { +public class NaiveTriggerComputer<RW extends MaterializedData & Writable> implements TriggerComputer<RW> { - private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; + private final FOQueryEvaluator<FOFormula, ? super QueryableData> evaluator; /** * Default constructor using the generic query evaluator @@ -29,19 +33,19 @@ public class NaiveTriggerComputer implements TriggerComputer { * Constructor using the given query evaluator * @param evaluator the query evaluator to use */ - public NaiveTriggerComputer(FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public NaiveTriggerComputer(FOQueryEvaluator<FOFormula, ? super QueryableData> evaluator) { this.evaluator = evaluator; } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { // Do nothing } @Override - public Iterator<Substitution> compute(FOQuery<?> body, FactBase fb) { + public Iterator<Substitution> compute(FOQuery<?> body, ChasableData<RW> chasableData) { try { - return this.evaluator.homomorphism(body, fb).iterator(); + return this.evaluator.homomorphism(body, chasableData.getAllReadableData()).iterator(); } catch (EvaluationException e) { throw new RuntimeException(e); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/SemiNaiveComputer.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/SemiNaiveComputer.java index c8aee3aa070e9f537320371c880f1ce16d91c651..46479a0e2cfa7e4b0d82d7db2099be51aed11716 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/SemiNaiveComputer.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/SemiNaiveComputer.java @@ -5,14 +5,15 @@ import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import java.util.Spliterator; -import java.util.Spliterators; import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.stream.StreamSupport; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.forward_chaining.chase.data.ChasableData; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.formula.api.FOFormulaConjunction; import fr.boreal.model.formula.factory.FOFormulaFactory; @@ -22,7 +23,6 @@ import fr.boreal.model.logicalElements.api.Predicate; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; import fr.boreal.model.logicalElements.api.Variable; -import fr.boreal.model.logicalElements.impl.AtomImpl; import fr.boreal.model.logicalElements.impl.SubstitutionImpl; import fr.boreal.model.query.api.FOQuery; import fr.boreal.model.query.factory.FOQueryFactory; @@ -36,12 +36,12 @@ import fr.boreal.query_evaluation.generic.GenericFOQueryEvaluator; * See <a href="https://wiki.epfl.ch/provenance2011/documents/foundations%20of%20databases-abiteboul-1995.pdf">...</a> * part 13.1 for more explanations */ -public class SemiNaiveComputer implements TriggerComputer { +public class SemiNaiveComputer<RW extends MaterializedData & Writable> implements TriggerComputer<RW> { - private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; - private Chase chase; + private final FOQueryEvaluator<FOFormula, ? super QueryableData> evaluator; + private Chase<RW> chase; - private final TriggerComputer fallback; + private final TriggerComputer<RW> fallback; /** * Default constructor using the generic query evaluator @@ -54,23 +54,23 @@ public class SemiNaiveComputer implements TriggerComputer { * Constructor using the given query evaluator * @param evaluator the query evaluator to use */ - public SemiNaiveComputer(FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public SemiNaiveComputer(FOQueryEvaluator<FOFormula, ? super QueryableData> evaluator) { this.evaluator = evaluator; - this.fallback = new NaiveTriggerComputer(this.evaluator); + this.fallback = new NaiveTriggerComputer<RW>(this.evaluator); } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.chase = c; this.fallback.init(c); } @Override - public Iterator<Substitution> compute(FOQuery<?> body, FactBase fb) { + public Iterator<Substitution> compute(FOQuery<?> body, ChasableData<RW> chasableData) { // First step if(chase.getLastStepResults().created_facts() == null) { - return this.fallback.compute(body, fb); + return this.fallback.compute(body, chasableData); } FactBase last_step_facts = chase.getLastStepResults().created_facts_as_factbase(); @@ -129,7 +129,7 @@ public class SemiNaiveComputer implements TriggerComputer { possible_triggers = possible_triggers.flatMap(substitution -> { FOQuery<FOFormulaConjunction> query_on_factbase = FOQueryFactory.instance().createOrGetQuery(atoms_on_factbase_formula, null); try { - return this.evaluator.homomorphism(query_on_factbase, fb, substitution) + return this.evaluator.homomorphism(query_on_factbase, chasableData.getAllReadableData(), substitution) .map(subs -> substitution.merged(subs).orElseThrow()); } catch (EvaluationException e) { throw new RuntimeException(e); @@ -143,7 +143,7 @@ public class SemiNaiveComputer implements TriggerComputer { try { return evaluator.homomorphism( FOQueryFactory.instance().createOrGetQuery(a, a.getVariables().toList()), - this.chase.getFactBase(), + this.chase.getChasableData().getAllReadableData(), substitution) .filter(s -> !last_step_facts.contains((Atom) s.createImageOf(a))) .map(subs -> substitution.merged(subs).orElseThrow()); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TriggerComputer.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TriggerComputer.java index 9f2e55d98a2047783a39fe0bbcb67a0f05e72dc0..d24eec83b0cac49cc6869bec94c5529129c804b0 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TriggerComputer.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TriggerComputer.java @@ -1,6 +1,10 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_computer; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.forward_chaining.chase.data.ChasableData; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.query.api.FOQuery; @@ -10,20 +14,20 @@ import java.util.Iterator; /** * Computes the triggers from a rule's body on a factbase */ -public interface TriggerComputer { +public interface TriggerComputer<RW extends MaterializedData & Writable> { /** * Initialize the trigger computer for the given chase * @param c the chase object */ - void init(Chase c); + void init(Chase<RW> c); /** * Computes and returns the triggers of the body on the factbase * @param body the body of the rule to evaluate - * @param fb the factbase on which to evaluate the rule + * @param chasableData the data to apply the rules on * @return the triggers of the rule on the factbase */ - Iterator<Substitution> compute(FOQuery<?> body, FactBase fb); + Iterator<Substitution> compute(FOQuery<?> body, ChasableData<RW> chasableData); } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TwoStepComputer.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TwoStepComputer.java index 3673436aac00ea3c1efe55aea906a11af36e79ee..492b7358805c8388df6c1b2c65e91498fd551e18 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TwoStepComputer.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/rule_applier/trigger_computer/TwoStepComputer.java @@ -1,7 +1,11 @@ package fr.boreal.forward_chaining.chase.rule_applier.trigger_computer; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.forward_chaining.chase.data.ChasableData; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; @@ -21,10 +25,10 @@ import java.util.stream.StreamSupport; * <p> * Send an atom on the new facts and extends the homomorphism to the factbase */ -public class TwoStepComputer implements TriggerComputer { +public class TwoStepComputer<RW extends MaterializedData & Writable> implements TriggerComputer<RW> { - private final FOQueryEvaluator<FOFormula, ? super FactBase> evaluator; - private Chase chase; + private final FOQueryEvaluator<FOFormula, ? super QueryableData> evaluator; + private Chase<RW> chase; /** * Default constructor using the generic query evaluator @@ -37,23 +41,23 @@ public class TwoStepComputer implements TriggerComputer { * Constructor using the given query evaluator * @param evaluator the query evaluator to use */ - public TwoStepComputer(FOQueryEvaluator<FOFormula, ? super FactBase> evaluator) { + public TwoStepComputer(FOQueryEvaluator<FOFormula, ? super QueryableData> evaluator) { this.evaluator = evaluator; } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.chase = c; } @Override - public Iterator<Substitution> compute(FOQuery<?> body, FactBase fb) { + public Iterator<Substitution> compute(FOQuery<?> body, ChasableData<RW> chasableData) { Collection<Atom> last_step_facts = this.chase.getLastStepResults().created_facts(); // First step if(last_step_facts == null) { try { - return this.evaluator.homomorphism(body, fb).iterator(); + return this.evaluator.homomorphism(body, chasableData.getAllReadableData()).iterator(); } catch (EvaluationException e) { throw new RuntimeException(e); } @@ -96,7 +100,7 @@ public class TwoStepComputer implements TriggerComputer { for (Atom a : partialS.keySet()) { for (Substitution s : partialS.get(a)) { try { - finalResult.add(this.evaluator.homomorphism(body, fb, s) + finalResult.add(this.evaluator.homomorphism(body, chasableData.getAllReadableData(), s) .map(subs -> s.merged(subs).orElseThrow()) .iterator()); } catch (EvaluationException e) { diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/AddCreatedFacts.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/AddCreatedFacts.java index f3bc1115928ffedca5ad2bba79ef1b14a27256ab..a9015e6876d8a0509e57b087ae6ad2b254955663 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/AddCreatedFacts.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/AddCreatedFacts.java @@ -1,6 +1,8 @@ package fr.boreal.forward_chaining.chase.treatment; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; @@ -10,19 +12,19 @@ import java.util.Collection; * When applied, this treatment adds the facts created at the previous step to the factbase * This is used for parallel application of rules. */ -public class AddCreatedFacts implements EndTreatment { +public class AddCreatedFacts<RW extends MaterializedData & Writable> implements EndTreatment<RW> { - private Chase c; + private Chase<RW> c; @Override public void apply() { - FactBase fb = c.getFactBase(); + RW fb = c.getChasableData().getWritingTarget(); Collection<Atom> new_facts = c.getLastStepResults().created_facts(); new_facts.forEach(fb::add); } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.c = c; } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeCore.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeCore.java index 522dcfdf63ea228a462ce4b59f87fd1b4f56e160..3216c128e2cef28c5090dc6c5871aae1844ff285 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeCore.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeCore.java @@ -2,6 +2,8 @@ package fr.boreal.forward_chaining.chase.treatment; import fr.boreal.core.CoreProcessor; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.logicalElements.api.Atom; import java.util.List; @@ -11,29 +13,29 @@ import java.util.List; * * @author Guillaume Pérution-Kihli */ -public class ComputeCore implements EndTreatment, Pretreatment { - private Chase chase; - final private CoreProcessor processor; +public class ComputeCore<RW extends MaterializedData & Writable> implements EndTreatment<RW>, Pretreatment<RW> { + private Chase<RW> chase; + final private CoreProcessor<RW> processor; - public ComputeCore(CoreProcessor processor) + public ComputeCore(CoreProcessor<RW> processor) { this.processor = processor; } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.chase = c; } @Override public void apply() { - this.processor.computeCore(this.chase.getFactBase()); + this.processor.computeCore(this.chase.getChasableData().getWritingTarget()); List<Atom> toRemove = this.chase.getLastStepResults() .created_facts() .stream() .flatMap(f -> f.asAtomSet().stream()) - .filter(a -> !this.chase.getFactBase().contains(a)) + .filter(a -> !this.chase.getChasableData().getWritingTarget().contains(a)) .toList(); this.chase.getLastStepResults().created_facts().removeAll(toRemove); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeLocalCore.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeLocalCore.java index 81a296cf2646cf3a8f63c9bc5cded403d1e2aeae..1d4c791a1fc39e69ad62094d17a7f5ab2594faaa 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeLocalCore.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/ComputeLocalCore.java @@ -2,6 +2,8 @@ package fr.boreal.forward_chaining.chase.treatment; import fr.boreal.core.CoreProcessor; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Variable; @@ -15,31 +17,31 @@ import java.util.stream.Collectors; * * @author Guillaume Pérution-Kihli */ -public class ComputeLocalCore implements EndTreatment { - private Chase chase; - final private CoreProcessor processor; +public class ComputeLocalCore<RW extends MaterializedData & Writable> implements EndTreatment<RW> { + private Chase<RW> chase; + final private CoreProcessor<RW> processor; Set<Variable> frozenVariables; - public ComputeLocalCore(CoreProcessor processor) + public ComputeLocalCore(CoreProcessor<RW> processor) { this.processor = processor; } @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.chase = c; - frozenVariables = this.chase.getFactBase().getVariables().collect(Collectors.toSet()); + frozenVariables = this.chase.getChasableData().getWritingTarget().getVariables().collect(Collectors.toSet()); } @Override public void apply() { - this.processor.computeCore(this.chase.getFactBase(), frozenVariables); - this.chase.getFactBase().getVariables().forEach(frozenVariables::add); + this.processor.computeCore(this.chase.getChasableData().getWritingTarget(), frozenVariables); + this.chase.getChasableData().getWritingTarget().getVariables().forEach(frozenVariables::add); List<Atom> toRemove = this.chase.getLastStepResults() .created_facts() .stream() - .filter(a -> !this.chase.getFactBase().contains(a)) + .filter(a -> !this.chase.getChasableData().getWritingTarget().contains(a)) .toList(); this.chase.getLastStepResults().created_facts().removeAll(toRemove); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Debug.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Debug.java index ff4a68c1a5a174164330875d0be9119c18982a24..07766f2663cb9c2bc726283ad3d6e2813784462d 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Debug.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Debug.java @@ -1,13 +1,15 @@ package fr.boreal.forward_chaining.chase.treatment; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; /** * When applied, this treatment prints informations about the chase, the current step and the factbase */ -public class Debug implements EndTreatment { +public class Debug<RW extends MaterializedData & Writable> implements EndTreatment<RW> { - private Chase c; + private Chase<RW> c; private long time; @@ -15,7 +17,7 @@ public class Debug implements EndTreatment { public void apply() { System.out.println("---"); System.out.println("Step : " + c.getStepCount()); - System.out.println("Atoms : " + c.getFactBase().size()); + System.out.println("Atoms : " + c.getChasableData().getWritingTarget().size()); System.out.println("Added atoms : " + c.getLastStepResults().created_facts().size()); System.out.println("Time : " + (System.currentTimeMillis() - time)); System.out.println("Last step rules : " + c.getLastStepResults().applied_rules().size()); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/EndTreatment.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/EndTreatment.java index 6be1ffcb498f20865632dcfe923c3d2fae8704f8..b9400368e27efa344a5aefd973bd057dab34fcab 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/EndTreatment.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/EndTreatment.java @@ -1,8 +1,11 @@ package fr.boreal.forward_chaining.chase.treatment; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; + /** * These treatments can be applied at the end of a step of the chase */ -public interface EndTreatment extends Treatment { +public interface EndTreatment<RW extends MaterializedData & Writable> extends Treatment<RW> { } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/PredicateFilterEndTreatment.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/PredicateFilterEndTreatment.java index 411068b541d66370627cffee485077ee59611bd4..254ac64d6e8532605f81758d1605f83cbc03fd00 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/PredicateFilterEndTreatment.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/PredicateFilterEndTreatment.java @@ -1,6 +1,8 @@ package fr.boreal.forward_chaining.chase.treatment; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Predicate; @@ -10,17 +12,17 @@ import java.util.*; /** * End treatment to filter out facts with predicates not in the provided list. */ -public class PredicateFilterEndTreatment implements EndTreatment { +public class PredicateFilterEndTreatment<RW extends MaterializedData & Writable> implements EndTreatment<RW> { private static final int BATCH_SIZE = 100; private final Map<Integer, Set<Predicate>> predicatesToRemoveByStep; - private Chase chase; + private Chase<RW> chase; public PredicateFilterEndTreatment(Map<Integer, Set<Predicate>> predicatesToRemoveByStep) { this.predicatesToRemoveByStep = predicatesToRemoveByStep; } @Override - public void init(Chase chase) { + public void init(Chase<RW> chase) { this.chase = chase; } @@ -29,7 +31,7 @@ public class PredicateFilterEndTreatment implements EndTreatment { int currentStep = chase.getStepCount(); Set<Predicate> predicatesToRemove = predicatesToRemoveByStep.getOrDefault(currentStep, Set.of()); - FactBase factBase = chase.getFactBase(); + RW factBase = chase.getChasableData().getWritingTarget(); for (Predicate predicate : predicatesToRemove) { List<Atom> batch = new ArrayList<>(BATCH_SIZE); diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Pretreatment.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Pretreatment.java index 85459c13eff5434ebaa7b368e7828f98d05d1e79..d76f435f4511c8e5f44cc148b57c9a670542049a 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Pretreatment.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Pretreatment.java @@ -1,8 +1,11 @@ package fr.boreal.forward_chaining.chase.treatment; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; + /** * These treatments can be applied at the start of a step of the chase */ -public interface Pretreatment extends Treatment { +public interface Pretreatment<RW extends MaterializedData & Writable> extends Treatment<RW> { } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/RuleSplit.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/RuleSplit.java index 04afeeaaa74c6335665444005717c7c050ba61c5..a0ecb96e95b80935a101ca427c9ec566091d04dc 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/RuleSplit.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/RuleSplit.java @@ -4,6 +4,8 @@ import java.util.HashSet; import java.util.Set; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; import fr.boreal.model.kb.api.RuleBase; import fr.boreal.model.kb.impl.RuleBaseImpl; import fr.boreal.model.rule.api.FORule; @@ -12,12 +14,12 @@ import fr.lirmm.boreal.util.Rules; /** * When applied, this treatment change the rulebase with an equivalent rule base containing only single piece rules. */ -public class RuleSplit implements Pretreatment { +public class RuleSplit<RW extends MaterializedData & Writable> implements Pretreatment<RW> { - private Chase chase; + private Chase<RW> chase; @Override - public void init(Chase c) { + public void init(Chase<RW> c) { this.chase = c; } diff --git a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Treatment.java b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Treatment.java index 531d5e59c29e35f53d632061029801fefb6aa37c..c249ee65d39b5eda19e9b7e744bf5a467ddceefb 100644 --- a/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Treatment.java +++ b/integraal/integraal-forward-chaining/src/main/java/fr/boreal/forward_chaining/chase/treatment/Treatment.java @@ -1,17 +1,19 @@ package fr.boreal.forward_chaining.chase.treatment; import fr.boreal.forward_chaining.chase.Chase; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; /** * Apply a given treatment */ -public interface Treatment { +public interface Treatment<RW extends MaterializedData & Writable> { /** * Initialize the treatment for the given chase * @param c the chase object */ - void init(Chase c); + void init(Chase<RW> c); /** * Applies the treatment diff --git a/integraal/integraal-forward-chaining/src/main/java/module-info.java b/integraal/integraal-forward-chaining/src/main/java/module-info.java index 67994cec8c0f21ed700317eeeedf3fedcd2b63ef..86d25a22bb868995077a6c4d6a7097b35d0f639f 100644 --- a/integraal/integraal-forward-chaining/src/main/java/module-info.java +++ b/integraal/integraal-forward-chaining/src/main/java/module-info.java @@ -30,4 +30,5 @@ module fr.boreal.forward_chaining { exports fr.boreal.forward_chaining.chase.rule_applier.trigger_computer; exports fr.boreal.forward_chaining.chase.rule_scheduler; exports fr.boreal.forward_chaining.chase.treatment; + exports fr.boreal.forward_chaining.chase.data; } \ No newline at end of file diff --git a/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeCoreTest.java b/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeCoreTest.java index d12ca928753630fcdf8f75fe2d44b3d717163a06..0645ac0d4ec7408a89e5f7dfbcb44331f035e1fb 100644 --- a/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeCoreTest.java +++ b/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeCoreTest.java @@ -3,6 +3,7 @@ package fr.boreal.forward_chaining.chase.test.treatment; import fr.boreal.core.*; import fr.boreal.forward_chaining.chase.Chase; import fr.boreal.forward_chaining.chase.ChaseBuilder; +import fr.boreal.forward_chaining.chase.data.ChasableDataImpl; import fr.boreal.forward_chaining.chase.treatment.ComputeCore; import fr.boreal.io.dlgp.DlgpParser; import fr.boreal.model.data.readable.exception.EvaluationException; @@ -47,10 +48,10 @@ public class ComputeCoreTest { .flatMap(ComputeCoreTest::addChase); } - private static Chase createChase (ChaseBuilder cb, Object[] testCase) { - return cb.addStepEndTreatments(new ComputeCore((CoreProcessor) testCase[2])) - .setFactBase(new SimpleInMemoryGraphStore(Objects - .requireNonNull(DlgpParser.parseFile((String) testCase[0])).atoms())) + private static Chase<FactBase> createChase (ChaseBuilder<FactBase> cb, Object[] testCase) { + return cb.addStepEndTreatments(new ComputeCore<>((CoreProcessor<FactBase>) testCase[2])) + .setChasableData(new ChasableDataImpl<>(new SimpleInMemoryGraphStore(Objects + .requireNonNull(DlgpParser.parseFile((String) testCase[0])).atoms()))) .setRuleBase(new RuleBaseImpl(Objects .requireNonNull(DlgpParser.parseFile((String) testCase[0])).rules())) .build().get(); @@ -80,10 +81,10 @@ public class ComputeCoreTest { @ParameterizedTest @MethodSource("provideData") - public void computeCoreTest(Chase chase, SimpleInMemoryGraphStore expected) { + public void computeCoreTest(Chase<FactBase> chase, SimpleInMemoryGraphStore expected) { chase.execute(); - Assertions.assertTrue(isACore(chase.getFactBase())); - Assertions.assertTrue(isEquivalent(chase.getFactBase(), expected)); + Assertions.assertTrue(isACore(chase.getChasableData().getWritingTarget())); + Assertions.assertTrue(isEquivalent(chase.getChasableData().getWritingTarget(), expected)); } private static boolean isACore(FactBase fb) { diff --git a/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeLocalCoreTest.java b/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeLocalCoreTest.java index 2e8a8169c53f707afa18b55b9b60777413a99817..487b6c2776602bca3b10c039092ce40e963cdc60 100644 --- a/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeLocalCoreTest.java +++ b/integraal/integraal-forward-chaining/src/test/java/fr/boreal/forward_chaining/chase/test/treatment/ComputeLocalCoreTest.java @@ -3,6 +3,7 @@ package fr.boreal.forward_chaining.chase.test.treatment; import fr.boreal.core.*; import fr.boreal.forward_chaining.chase.Chase; import fr.boreal.forward_chaining.chase.ChaseBuilder; +import fr.boreal.forward_chaining.chase.data.ChasableDataImpl; import fr.boreal.forward_chaining.chase.treatment.ComputeLocalCore; import fr.boreal.io.dlgp.DlgpParser; import fr.boreal.model.data.readable.exception.EvaluationException; @@ -31,15 +32,15 @@ public class ComputeLocalCoreTest { static Stream<Object[]> provideData() { return Arrays.stream(new CoreProcessor[] { - new MultiThreadsByPieceCoreProcessor( + new MultiThreadsByPieceCoreProcessor<>( 16, MultiThreadsByPieceCoreProcessor.Variant.BY_SPECIALISATION), - new MultiThreadsByPieceCoreProcessor( + new MultiThreadsByPieceCoreProcessor<>( 16, MultiThreadsByPieceCoreProcessor.Variant.BY_DELETION), - new MultiThreadsByPieceCoreProcessor( + new MultiThreadsByPieceCoreProcessor<>( 16, MultiThreadsByPieceCoreProcessor.Variant.EXHAUSTIVE), - new ByPieceCoreProcessor(ByPieceCoreProcessor.Variant.BY_SPECIALISATION), - new ByPieceCoreProcessor(ByPieceCoreProcessor.Variant.BY_DELETION), - new ByPieceCoreProcessor(ByPieceCoreProcessor.Variant.EXHAUSTIVE), + new ByPieceCoreProcessor<>(ByPieceCoreProcessor.Variant.BY_SPECIALISATION), + new ByPieceCoreProcessor<>(ByPieceCoreProcessor.Variant.BY_DELETION), + new ByPieceCoreProcessor<>(ByPieceCoreProcessor.Variant.EXHAUSTIVE), new NaiveCoreProcessor(), new ByPieceAndVariableCoreProcessor() }) @@ -47,10 +48,10 @@ public class ComputeLocalCoreTest { .flatMap(ComputeLocalCoreTest::addChase); } - private static Chase createChase (ChaseBuilder cb, Object[] testCase) { - return cb.addStepEndTreatments(new ComputeLocalCore((CoreProcessor) testCase[2])) - .setFactBase(new SimpleInMemoryGraphStore(Objects - .requireNonNull(DlgpParser.parseFile((String) testCase[0])).atoms())) + private static Chase<FactBase> createChase (ChaseBuilder<FactBase> cb, Object[] testCase) { + return cb.addStepEndTreatments(new ComputeLocalCore<>((CoreProcessor<FactBase>) testCase[2])) + .setChasableData(new ChasableDataImpl<>(new SimpleInMemoryGraphStore(Objects + .requireNonNull(DlgpParser.parseFile((String) testCase[0])).atoms()))) .setRuleBase(new RuleBaseImpl(Objects .requireNonNull(DlgpParser.parseFile((String) testCase[0])).rules())) .build().get(); @@ -79,10 +80,10 @@ public class ComputeLocalCoreTest { @ParameterizedTest @MethodSource("provideData") - public void computeCoreTest(Chase chase, SimpleInMemoryGraphStore expected) { + public void computeCoreTest(Chase<FactBase> chase, SimpleInMemoryGraphStore expected) { chase.execute(); - Assertions.assertTrue(isACore(chase.getFactBase())); - Assertions.assertTrue(isEquivalent(chase.getFactBase(), expected)); + Assertions.assertTrue(isACore(chase.getChasableData().getWritingTarget())); + Assertions.assertTrue(isEquivalent(chase.getChasableData().getWritingTarget(), expected)); } private static boolean isACore(FactBase fb) { diff --git a/integraal/integraal-io/src/main/java/fr/boreal/io/api/Parser.java b/integraal/integraal-io/src/main/java/fr/boreal/io/api/Parser.java index 5612918a16f101fa7d1b8469ca14786b0a287bdb..e0676ac397f223124b64264af38db94eb1d35258 100644 --- a/integraal/integraal-io/src/main/java/fr/boreal/io/api/Parser.java +++ b/integraal/integraal-io/src/main/java/fr/boreal/io/api/Parser.java @@ -48,7 +48,8 @@ import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.query.api.Query; import fr.boreal.model.rule.api.FORule; import fr.boreal.views.builder.ViewBuilder; -import fr.boreal.views.datasource.AbstractViewWrapper; +import fr.boreal.views.datasource.AbstractDataSource; +import fr.boreal.views.datasource.DataSource; import fr.lirmm.boreal.util.stream.CloseableIterator; import java.util.*; @@ -77,7 +78,7 @@ public interface Parser<T> extends CloseableIterator<T> { Collection<Atom> atoms = new ArrayList<>(); Collection<FORule> rules = new ArrayList<>(); Collection<Query> queries = new ArrayList<>(); - Collection<AbstractViewWrapper<String, ?>> views = new LinkedHashSet<>(); + Collection<DataSource<String, ?>> views = new LinkedHashSet<>(); while (this.hasNext()) { switch (this.next()) { @@ -85,7 +86,7 @@ public interface Parser<T> extends CloseableIterator<T> { case FORule r -> rules.add(r); case Query q -> queries.add(q); case Directive d when d.type().equals(Directive.Type.VIEW) -> - views.addAll(ViewBuilder.createFactBases(d.value().toString())); + views.addAll(ViewBuilder.loadDataSources(d.value().toString())); default -> { } } diff --git a/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/InternalObjectFactory.java b/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/InternalObjectFactory.java index 8c8118cdfa752a23ac3ac41c5bc74dce4fc33266..f0488a249b50beb92c2f7f50b06893761741dc49 100644 --- a/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/InternalObjectFactory.java +++ b/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/InternalObjectFactory.java @@ -51,8 +51,6 @@ import fr.boreal.model.functions.JavaMethodInvoker; import fr.boreal.model.logicalElements.api.Term; import fr.boreal.model.logicalElements.factory.api.TermFactory; import fr.boreal.model.logicalElements.impl.functionalTerms.EvaluableFunctionImpl; -import fr.boreal.model.logicalElements.impl.functionalTerms.GroundFunctionalTermImpl; -import fr.boreal.model.logicalElements.impl.functionalTerms.SpecializableFunctionalTermImpl; import fr.lirmm.graphik.dlgp3.parser.ADlgpItemFactory; import fr.lirmm.graphik.dlgp3.parser.BuildException; import fr.lirmm.graphik.dlgp3.parser.InvokeManager; diff --git a/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/ParserResult.java b/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/ParserResult.java index 06e25a3cbace2f3e8b06203f43c9a2fc6bd0ed62..26cacd6e2eb508f0640786fb58ba5ee63d51b2a0 100644 --- a/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/ParserResult.java +++ b/integraal/integraal-io/src/main/java/fr/boreal/io/dlgp/ParserResult.java @@ -1,12 +1,13 @@ package fr.boreal.io.dlgp; -import java.util.Collection; -import java.util.LinkedHashSet; - import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.query.api.Query; import fr.boreal.model.rule.api.FORule; -import fr.boreal.views.datasource.AbstractViewWrapper; +import fr.boreal.views.datasource.AbstractDataSource; +import fr.boreal.views.datasource.DataSource; + +import java.util.Collection; +import java.util.LinkedHashSet; /** * Result of the DLGP parsing @@ -19,7 +20,7 @@ public record ParserResult( Collection<Atom> atoms, Collection<FORule> rules, Collection<Query> queries, - Collection<AbstractViewWrapper<String, ?>> views) { + Collection<DataSource<String, ?>> views) { /** * Creates a union of two DlgpParserResult records. @@ -33,7 +34,7 @@ public record ParserResult( Collection<Atom> unionAtoms = new LinkedHashSet<>(this.atoms); Collection<FORule> unionRules = new LinkedHashSet<>(this.rules); Collection<Query> unionQueries = new LinkedHashSet<>(this.queries); - Collection<AbstractViewWrapper<String, ?>> unionViews = new LinkedHashSet<>(this.views); + Collection<DataSource<String, ?>> unionViews = new LinkedHashSet<>(this.views); // Add all elements from the other DlgpParserResult to the collections unionAtoms.addAll(other.atoms); diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/MaterializedDataCollection.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/MaterializedDataCollection.java new file mode 100644 index 0000000000000000000000000000000000000000..cfdc392d1f69e3491c9c9f53cb1ccfef80f5710c --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/MaterializedDataCollection.java @@ -0,0 +1,120 @@ +package fr.boreal.model.data.collection.api; + +import fr.boreal.model.data.collection.impl.MaterializedDataCollectionImpl; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.logicalElements.api.*; + +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +public interface MaterializedDataCollection<T extends MaterializedData> + extends QueryableDataCollection<T>, MaterializedData { + @Override + default Stream<Atom> getAtoms() { + return this.getAllQueryableData().values().stream() + .flatMap(MaterializedData::getAtoms); + } + + @Override + default Set<Atom> getAtomSet() { + return new AbstractSet<>() { // We build a view so that it does not consume more memory + @Override + public Iterator<Atom> iterator() { + return getAtoms().iterator(); + } + + @Override + public int size() { + return getAllQueryableData().values().stream() + .mapToInt(md -> (int) md.size()) + .sum(); + } + + @Override + public boolean contains(Object o) { + if (!(o instanceof Atom a)) { + return false; + } + return MaterializedDataCollection.this.contains(a); + } + }; + } + + @Override + default Stream<Atom> getAtomsByTerm(Term term) { + return this.getAllQueryableData().values().stream() + .flatMap(md -> md.getAtomsByTerm(term)); + } + + @Override + default Stream<Term> getTermsByPredicatePosition(Predicate p, int position) { + Optional<T> md = getQueryableData(p); + if (md.isPresent()) { + return md.get().getTermsByPredicatePosition(p, position); + } + + return Stream.empty(); + } + + @Override + default boolean contains(Atom a) { + Optional<T> md = getQueryableData(a.getPredicate()); + return md.map(atoms -> atoms.contains(a)).orElse(false); + } + + @Override + default long size() { + return this.getAllQueryableData().values().stream() + .mapToLong(MaterializedData::size) + .sum(); + } + + @Override + default Stream<Atom> getAtomsByPredicate(Predicate predicate) { + Optional<T> md = getQueryableData(predicate); + if (md.isPresent()) { + return md.get().getAtomsByPredicate(predicate); + } + + return Stream.empty(); + } + + @Override + default Stream<Term> getTerms() { + return this.getAllQueryableData().values().stream() + .flatMap(MaterializedData::getTerms); + } + + @Override + default Stream<Variable> getVariables() { + return this.getAllQueryableData().values().stream() + .flatMap(MaterializedData::getVariables); + } + + @Override + default Stream<Literal<?>> getLiterals() { + return this.getAllQueryableData().values().stream() + .flatMap(MaterializedData::getLiterals); + } + + @Override + default Stream<Constant> getConstants() { + return this.getAllQueryableData().values().stream() + .flatMap(MaterializedData::getConstants); + } + + @Override + default Stream<Term> getAllNestedTerms() { + return this.getAllQueryableData().values().stream() + .flatMap(MaterializedData::getAllNestedTerms); + } + + @Override + default <TT extends Term> Stream<TT> getNestedTerms(Class<TT> classType) { + return this.getAllQueryableData().values().stream() + .flatMap(md -> md.getNestedTerms(classType)); + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/MaterializedWritableDataCollection.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/MaterializedWritableDataCollection.java new file mode 100644 index 0000000000000000000000000000000000000000..da5b34b7094d20d1f967da39e334f10ea165cedc --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/MaterializedWritableDataCollection.java @@ -0,0 +1,7 @@ +package fr.boreal.model.data.collection.api; + +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; + +public interface MaterializedWritableDataCollection<Q extends MaterializedData, W extends Writable> + extends MaterializedDataCollection<Q>, QueryableWritableDataCollection<Q, W> {} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/QueryableDataCollection.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/QueryableDataCollection.java new file mode 100644 index 0000000000000000000000000000000000000000..478e009b3e07b682d9ebde1b24983cad92f2fd99 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/QueryableDataCollection.java @@ -0,0 +1,60 @@ +package fr.boreal.model.data.collection.api; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.readable.query.AtomicPattern; +import fr.boreal.model.data.readable.query.AtomicPatternBuilder; +import fr.boreal.model.data.readable.query.BasicQuery; +import fr.boreal.model.logicalElements.api.Predicate; +import fr.boreal.model.logicalElements.api.Term; + +import java.util.*; +import java.util.stream.Stream; + +public interface QueryableDataCollection<T extends QueryableData> extends QueryableData { + ImmutableMap<Predicate, T> getAllQueryableData(); + + default Optional<T> getQueryableData(Predicate predicate) { + return Optional.ofNullable(getAllQueryableData().get(predicate)); + } + + @Override + default Collection<Predicate> getPredicates() { + return getAllQueryableData().keySet(); + } + + @Override + default Stream<List<Term>> evaluate(BasicQuery query) throws EvaluationException { + Optional<T> queryableData = this.getQueryableData(query.getPredicate()); + if (queryableData.isEmpty()) { + return Stream.empty(); + } + + return queryableData.get().evaluate(query); + } + + @Override + default Optional<Long> estimateBound(BasicQuery query) { + Optional<T> queryableData = this.getQueryableData(query.getPredicate()); + if (queryableData.isEmpty()) { + return Optional.of(0L); + } + + return queryableData.get().estimateBound(query); + } + + @Override + default AtomicPattern getBasicPattern(Predicate predicate) { + Optional<T> queryableData = this.getQueryableData(predicate); + if (queryableData.isEmpty()) { + return new AtomicPatternBuilder() + .withPredicate(predicate) + .withCreateQueriesFunction((p, pa) -> Stream.empty()) + .withIndexablePatternsFunction(p -> Set.of()) + .build(); + } + + return queryableData.get().getBasicPattern(predicate); + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/QueryableWritableDataCollection.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/QueryableWritableDataCollection.java new file mode 100644 index 0000000000000000000000000000000000000000..ed9e2a939fb47c9c070d7a6fe4120aa8a5b22b66 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/api/QueryableWritableDataCollection.java @@ -0,0 +1,80 @@ +package fr.boreal.model.data.collection.api; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; +import fr.boreal.model.logicalElements.api.Atom; +import fr.boreal.model.logicalElements.api.Predicate; + +import java.util.Map; +import java.util.Optional; + +public interface QueryableWritableDataCollection<Q extends QueryableData, W extends Writable> + extends QueryableDataCollection<Q>, Writable { + /** + * Get all the writable data by Predicate + * @return a map from predicates to the writable data + */ + ImmutableMap<Predicate, W> getAllWritableData(); + + /** + * Get the default-writable data, if provided + * The default-writable data is where atoms are written if they have a predicate not assigned to a writable + * @return an optional, containing the default writable, if provided + */ + Optional<W> getDefaultWritableData(); + + /** + * Get a writable by predicate + * Return the writable bind to a predicate or, if the predicate is not bound to a writable, the default + * writable + * @param predicate the predicate for which we want to get the writable data + * @return an optional containing the writable bound to a predicate or the default writable if available + */ + default Optional<W> getWritable(Predicate predicate) { + Map<Predicate, W> map = this.getAllWritableData(); + if (map.containsKey(predicate)) { + return Optional.of(map.get(predicate)); + } + + return getDefaultWritableData(); + } + + @Override + default boolean add(Atom atom) { + return this.findTargetWritableOrElseThrow(atom.getPredicate()).add(atom); + } + + @Override + default boolean remove(Atom atom) { + Optional<W> optional = this.getWritable(atom.getPredicate()); + if (optional.isPresent()) { + return optional.get().remove(atom); + } + + if (this.getQueryableData(atom.getPredicate()).isPresent()) { + throw new RuntimeException(String.format( + "Cannot remove %s since it is in read-only data", atom)); + } + + return false; + } + + @Override + default void clear() { + for (Q qd: this.getAllQueryableData().values()) { + if (!(qd instanceof Writable)) { + throw new RuntimeException("This data collection is not clearable as it contains read-only data."); + } + } + + this.getAllWritableData().values().forEach(W::clear); + this.getDefaultWritableData().ifPresent(Writable::clear); + } + + private W findTargetWritableOrElseThrow(Predicate predicate) throws RuntimeException { + return getWritable(predicate).orElseThrow(() -> new RuntimeException( + String.format("Could not find writeable target for %s", predicate) + )); + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/builder/ReadOnlyDataCollectionBuilder.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/builder/ReadOnlyDataCollectionBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..1fc2aa83c74f690d9163c0f9eae109ce106dcf04 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/builder/ReadOnlyDataCollectionBuilder.java @@ -0,0 +1,129 @@ +package fr.boreal.model.data.collection.builder; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.collection.api.MaterializedDataCollection; +import fr.boreal.model.data.collection.api.QueryableDataCollection; +import fr.boreal.model.data.collection.impl.MaterializedDataCollectionImpl; +import fr.boreal.model.data.collection.impl.QueryableDataCollectionImpl; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.logicalElements.api.Predicate; + +import java.util.*; + +/** + * A builder for creating read-only data collections. + * + * @param <T> the type of QueryableData to be stored in the collection + */ +public class ReadOnlyDataCollectionBuilder<T extends QueryableData> { + private final Map<Predicate, T> dataMap = new HashMap<>(); + + /** + * Adds a QueryableData instance associated with a specific Predicate. + * + * @param predicate the predicate associated with the QueryableData + * @param queryableData the QueryableData to be added + * @return this builder instance for chaining + * @throws IllegalArgumentException if the predicate is not present in the QueryableData + * @throws IllegalStateException if the predicate is already associated with another QueryableData + */ + public ReadOnlyDataCollectionBuilder<T> addQueryableData(Predicate predicate, T queryableData) { + Objects.requireNonNull(predicate, "Predicate cannot be null"); + Objects.requireNonNull(queryableData, "QueryableData cannot be null"); + + if (queryableData instanceof QueryableDataCollection<?>) { + QueryableDataCollection<T> collection = (QueryableDataCollection<T>) queryableData; + Optional<T> matchingQueryable = collection.getQueryableData(predicate); + if (matchingQueryable.isPresent()) { + return addQueryableData(predicate, matchingQueryable.get()); + } else { + throw new IllegalArgumentException("The provided QueryableDataCollection does not contain the given Predicate: " + predicate); + } + } + + if (dataMap.containsKey(predicate)) { + throw new IllegalStateException("The Predicate is already associated with another QueryableData: " + predicate); + } + + dataMap.put(predicate, queryableData); + return this; + } + + /** + * Adds a QueryableData instance with all its predicates. + * + * @param queryableData the QueryableData to be added + * @return this builder instance for chaining + * @throws IllegalStateException if any predicate is already associated with another QueryableData + */ + public ReadOnlyDataCollectionBuilder<T> addQueryableData(T queryableData) { + Objects.requireNonNull(queryableData, "QueryableData cannot be null"); + + if (queryableData instanceof QueryableDataCollection<?>) { + for (T subQueryable : ((QueryableDataCollection<T>) queryableData).getAllQueryableData().values()) { + addQueryableData(subQueryable); + } + } else { + for (Predicate predicate : queryableData.getPredicates()) { + this.addQueryableData(predicate, queryableData); + } + } + return this; + } + + /** + * Adds a QueryableData instance with specific predicates + * + * @param predicates the predicates associated with the QueryableData + * @param queryableData the QueryableData to be added + * @return this builder instance for chaining + * @throws IllegalStateException if any predicate is already associated with another QueryableData + */ + public ReadOnlyDataCollectionBuilder<T> addQueryableData(Collection<Predicate> predicates, T queryableData) { + Objects.requireNonNull(queryableData, "QueryableData cannot be null"); + Objects.requireNonNull(predicates, "predicates cannot be null"); + + for (Predicate predicate: predicates) { + this.addQueryableData(predicate, queryableData); + } + + return this; + } + + /** + * Builds a QueryableDataCollection instance from the added QueryableData. + * + * @return an immutable QueryableDataCollection instance + */ + public QueryableDataCollection<T> build() { + ImmutableMap<Predicate, T> immutableMap = ImmutableMap.copyOf(dataMap); + return new QueryableDataCollectionImpl<>(immutableMap) {}; + } + + /** + * Builds a MaterializedDataCollection instance if the type supports MaterializedData. + * + * @return an immutable MaterializedDataCollection instance + * @throws IllegalStateException if the type is not assignable to MaterializedData + */ + @SuppressWarnings("unchecked") + public MaterializedDataCollection<MaterializedData> buildMaterialized() { + if (!checkAllMaterialized()) { + throw new IllegalStateException("Cannot build a MaterializedDataCollection when the type is not MaterializedData"); + } + ImmutableMap<Predicate, MaterializedData> immutableMap = + ImmutableMap.copyOf((ImmutableMap<Predicate, MaterializedData>)dataMap); + return new MaterializedDataCollectionImpl<>(immutableMap) {}; + } + + @SuppressWarnings("unchecked") + private boolean checkAllMaterialized() { + for (T qd: this.dataMap.values()) { + if (!(qd instanceof MaterializedData)) { + return false; + } + } + return true; + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/builder/ReadWriteDataCollectionBuilder.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/builder/ReadWriteDataCollectionBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..45ccba8268a61d4a6440579d4114841c4958f723 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/builder/ReadWriteDataCollectionBuilder.java @@ -0,0 +1,143 @@ +package fr.boreal.model.data.collection.builder; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.collection.api.MaterializedWritableDataCollection; +import fr.boreal.model.data.collection.api.QueryableDataCollection; +import fr.boreal.model.data.collection.api.QueryableWritableDataCollection; +import fr.boreal.model.data.collection.impl.MaterializedWritableDataCollectionImpl; +import fr.boreal.model.data.collection.impl.QueryableWritableDataCollectionImpl; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; +import fr.boreal.model.logicalElements.api.Predicate; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * A builder for creating read-write data collections. + * + * @param <W> the type of Writable data associated with the collection, which also extends Q + */ +public class ReadWriteDataCollectionBuilder<W extends QueryableData & Writable> { + private final Map<Predicate, QueryableData> queryableDataMap = new HashMap<>(); + private final Map<Predicate, W> writableDataMap = new HashMap<>(); + private W defaultWritableData = null; + + + /** + * Adds a QueryableData instance associated with a specific Predicate. + * + * @param predicate the predicate associated with the QueryableData + * @param queryableData the QueryableData to be added + * @return this builder instance for chaining + * @throws IllegalArgumentException if the predicate is not present in the QueryableData + * @throws IllegalStateException if the predicate is already associated with another QueryableData + */ + public ReadWriteDataCollectionBuilder<W> addQueryableData(Predicate predicate, QueryableData queryableData) { + Objects.requireNonNull(predicate, "Predicate cannot be null"); + Objects.requireNonNull(queryableData, "QueryableData cannot be null"); + + if (queryableData instanceof QueryableDataCollection<?>) { + QueryableDataCollection<QueryableData> collection = (QueryableDataCollection<QueryableData>) queryableData; + Optional<QueryableData> matchingQueryable = collection.getQueryableData(predicate); + if (matchingQueryable.isPresent()) { + return addQueryableData(predicate, matchingQueryable.get()); + } else { + throw new IllegalArgumentException("The provided QueryableDataCollection does not contain the given Predicate: " + predicate); + } + } + + if (queryableDataMap.containsKey(predicate)) { + throw new IllegalStateException("The Predicate is already associated with another QueryableData: " + predicate); + } + + queryableDataMap.put(predicate, queryableData); + return this; + } + + /** + * Adds a QueryableData instance with all its predicates. + * + * @param queryableData the QueryableData to be added + * @return this builder instance for chaining + * @throws IllegalStateException if any predicate is already associated with another QueryableData + */ + public ReadWriteDataCollectionBuilder<W> addQueryableData(QueryableData queryableData) { + Objects.requireNonNull(queryableData, "QueryableData cannot be null"); + + if (queryableData instanceof QueryableDataCollection<?>) { + for (QueryableData subQueryable : ((QueryableDataCollection<QueryableData>) queryableData).getAllQueryableData().values()) { + addQueryableData(subQueryable); + } + } else { + for (Predicate predicate : queryableData.getPredicates()) { + this.addQueryableData(predicate, queryableData); + } + } + return this; + } + + /** + * Adds a Writable instance, which is also Queryable, associated with a specific Predicate. + */ + public ReadWriteDataCollectionBuilder<W> addQueryableWritableData(Predicate predicate, W writableData) { + addQueryableData(predicate, writableData); + writableDataMap.put(predicate, writableData); + return this; + } + + /** + * Sets the default Writable instance. + */ + public ReadWriteDataCollectionBuilder<W> setDefaultWritableData(W writableData) { + Objects.requireNonNull(writableData, "Default Writable cannot be null"); + this.defaultWritableData = writableData; + return this; + } + + /** + * Builds a QueryableWritableDataCollection instance from the added data. + */ + public <T extends QueryableData> QueryableWritableDataCollection<T, W> build() { + ImmutableMap<Predicate, T> immutableQueryableMap = (ImmutableMap<Predicate, T>) ImmutableMap.copyOf(queryableDataMap); + ImmutableMap<Predicate, W> immutableWritableMap = ImmutableMap.copyOf(writableDataMap); + return new QueryableWritableDataCollectionImpl<>(immutableQueryableMap, defaultWritableData, immutableWritableMap) {}; + } + + /** + * Builds a MaterializedWritableDataCollection instance if the type supports MaterializedData. + */ + public <T extends MaterializedData> MaterializedWritableDataCollection<T, W> buildMaterialized() { + if (!checkAllMaterialized()) { + throw new IllegalStateException("Cannot build a MaterializedDataCollection when the type is not MaterializedData"); + } + ImmutableMap<Predicate, T> immutableQueryableMap = + ImmutableMap.copyOf(queryableDataMap.keySet().stream() + .map(k -> Map.entry(k, (T)queryableDataMap.get(k))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); + ImmutableMap<Predicate, W> immutableWritableMap = ImmutableMap.copyOf(writableDataMap); + return new MaterializedWritableDataCollectionImpl<>( + immutableQueryableMap, + defaultWritableData, + immutableWritableMap) {}; + } + + @SuppressWarnings("unchecked") + private boolean checkAllMaterialized() { + for (QueryableData qd: this.queryableDataMap.values()) { + if (!(qd instanceof MaterializedData)) { + return false; + } + } + for (QueryableData qd: this.writableDataMap.values()) { + if (!(qd instanceof MaterializedData)) { + return false; + } + } + return true; + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/MaterializedDataCollectionImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/MaterializedDataCollectionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..de2f98075582d4b46e7d5b9c6145cfd1292795ea --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/MaterializedDataCollectionImpl.java @@ -0,0 +1,13 @@ +package fr.boreal.model.data.collection.impl; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.collection.api.MaterializedDataCollection; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.logicalElements.api.Predicate; + +public class MaterializedDataCollectionImpl<T extends MaterializedData> + extends QueryableDataCollectionImpl<T> implements MaterializedDataCollection<T> { + protected MaterializedDataCollectionImpl(ImmutableMap<Predicate, T> queryableData) { + super(queryableData); + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/MaterializedWritableDataCollectionImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/MaterializedWritableDataCollectionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..160e788b86dd57c050348f0ed59b3e16bfd5979a --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/MaterializedWritableDataCollectionImpl.java @@ -0,0 +1,18 @@ +package fr.boreal.model.data.collection.impl; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.collection.api.MaterializedWritableDataCollection; +import fr.boreal.model.data.readable.MaterializedData; +import fr.boreal.model.data.writable.Writable; +import fr.boreal.model.logicalElements.api.Predicate; + +public class MaterializedWritableDataCollectionImpl<Q extends MaterializedData, W extends Writable> + extends QueryableWritableDataCollectionImpl<Q, W> + implements MaterializedWritableDataCollection<Q, W> { + protected MaterializedWritableDataCollectionImpl( + ImmutableMap<Predicate, Q> queryableData, + W defaultWritableData, + ImmutableMap<Predicate, W> writableData) { + super(queryableData, defaultWritableData, writableData); + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/QueryableDataCollectionImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/QueryableDataCollectionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8d7aa582071e823249e2975f5c11b9aad0ae4f72 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/QueryableDataCollectionImpl.java @@ -0,0 +1,19 @@ +package fr.boreal.model.data.collection.impl; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.collection.api.QueryableDataCollection; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.logicalElements.api.Predicate; + +public class QueryableDataCollectionImpl<T extends QueryableData> implements QueryableDataCollection<T> { + ImmutableMap<Predicate, T> queryableData; + + protected QueryableDataCollectionImpl(ImmutableMap<Predicate, T> queryableData) { + this.queryableData = queryableData; + } + + @Override + public ImmutableMap<Predicate, T> getAllQueryableData() { + return this.queryableData; + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/QueryableWritableDataCollectionImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/QueryableWritableDataCollectionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..c20c3c31edecf5d3d4986bbba4d611fbb48a34f6 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/collection/impl/QueryableWritableDataCollectionImpl.java @@ -0,0 +1,36 @@ +package fr.boreal.model.data.collection.impl; + +import com.google.common.collect.ImmutableMap; +import fr.boreal.model.data.collection.api.QueryableWritableDataCollection; +import fr.boreal.model.data.readable.QueryableData; +import fr.boreal.model.data.writable.Writable; +import fr.boreal.model.logicalElements.api.Predicate; + +import java.util.Optional; + +public class QueryableWritableDataCollectionImpl<Q extends QueryableData, W extends Writable> + extends QueryableDataCollectionImpl<Q> + implements QueryableWritableDataCollection<Q, W> { + + final W defaultWritableData; + final ImmutableMap<Predicate, W> writableData; + + protected QueryableWritableDataCollectionImpl( + ImmutableMap<Predicate, Q> queryableData, + W defaultWritableData, + ImmutableMap<Predicate, W> writableData) { + super(queryableData); + this.defaultWritableData = defaultWritableData; + this.writableData = writableData; + } + + @Override + public ImmutableMap<Predicate, W> getAllWritableData() { + return writableData; + } + + @Override + public Optional<W> getDefaultWritableData() { + return Optional.ofNullable(defaultWritableData); + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/MaterializedData.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/MaterializedData.java index 768de9ce31ea2e676265b44e098eb656eae82795..316f4496b0a9c4cbd7d927c2085777f47607ebed 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/MaterializedData.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/MaterializedData.java @@ -84,12 +84,7 @@ public interface MaterializedData extends QueryableData, TermCompound, Iterable< try { return this.evaluate( this.getBasicPattern(predicate) - .createQueries( - IntStream.range(0, predicate.arity()).boxed() - .map(i -> (Term) SameObjectTermFactory.instance().createOrGetFreshVariable()) - .toList(), - new SubstitutionImpl() - ).findFirst().orElseThrow() + .createQueries(Map.of()).findFirst().orElseThrow() ).map(termList -> new AtomImpl(predicate, termList)); } catch (EvaluationException e) { throw new RuntimeException(e); diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/QueryableData.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/QueryableData.java index 31b4413987d28b0093260c6feade8a7cdf49f94c..fd30a5ac0e1ad79ef1dda6e8bf357275cc15ad0d 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/QueryableData.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/QueryableData.java @@ -1,12 +1,10 @@ package fr.boreal.model.data.readable; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; +import fr.boreal.model.data.readable.query.AtomicPattern; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Predicate; -import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; -import fr.boreal.model.query.api.Query; import java.util.Collection; import java.util.List; @@ -51,5 +49,5 @@ public interface QueryableData { * @param predicate the predicate for which we want to know the basic pattern * @return a basic pattern for predicate */ - BasicPattern getBasicPattern(Predicate predicate); + AtomicPattern getBasicPattern(Predicate predicate); } diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AbstractAtomicPattern.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AbstractAtomicPattern.java new file mode 100644 index 0000000000000000000000000000000000000000..0653cd269881342bc07795e87ffe6c27eaf626a7 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AbstractAtomicPattern.java @@ -0,0 +1,58 @@ +package fr.boreal.model.data.readable.query; + +import fr.boreal.model.logicalElements.api.Predicate; +import fr.boreal.model.logicalElements.api.Substitution; +import fr.boreal.model.logicalElements.api.Term; + +import java.util.List; +import java.util.Map; +import java.util.Collections; + +import java.util.*; +import java.util.stream.Stream; + +/** + * Represents a basic pattern for querying predicates with specific constraints on term positions. + * This pattern defines which positions must be specified (Mandatory), which can be indexed (Indexable), + * and what types of terms are allowed in each position. + */ +public abstract class AbstractAtomicPattern implements AtomicPattern { + + private final Predicate predicate; + private final Set<Integer> mandatoryPositions; + private final Map<Integer, Class<? extends Term>> termConstraints; + + /** + * Constructs an AtomicPattern with specific constraints. + * + * @param predicate The predicate associated with this pattern. + * @param mandatoryPositions A list of positions that are mandatory. + * @param termConstraints A map associating positions (0-based index) with allowed term types. + */ + public AbstractAtomicPattern(Predicate predicate, Set<Integer> mandatoryPositions, + Map<Integer, Class<? extends Term>> termConstraints) { + this.predicate = predicate; + this.mandatoryPositions = Collections.unmodifiableSet(mandatoryPositions); + this.termConstraints = Collections.unmodifiableMap(termConstraints); + } + + @Override + public Predicate getPredicate() { + return predicate; + } + + @Override + public Class<? extends Term> getTermConstraint(int position) { + return termConstraints.get(position); + } + + @Override + public Set<Integer> getMandatoryPositions() { + return mandatoryPositions; + } + + @Override + public boolean hasAssignedMandatoryParameters(Map<Integer, Term> positionsAssignation) { + return positionsAssignation.keySet().containsAll(mandatoryPositions); + } +} \ No newline at end of file diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AtomicPattern.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AtomicPattern.java new file mode 100644 index 0000000000000000000000000000000000000000..31485e4ed815d2566251c7fbe033a411c6c7daf9 --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AtomicPattern.java @@ -0,0 +1,58 @@ +package fr.boreal.model.data.readable.query; + +import fr.boreal.model.logicalElements.api.Predicate; +import fr.boreal.model.logicalElements.api.Substitution; +import fr.boreal.model.logicalElements.api.Term; + +import java.util.List; + +import java.util.*; +import java.util.stream.Stream; + +/** + * Represents a basic pattern for querying predicates with specific constraints on term positions. + * This pattern defines which positions must be specified (Mandatory), which can be indexed (Indexable), + * and what types of terms are allowed in each position. + */ +public interface AtomicPattern { + + /** + * @return The predicate associated with this pattern. + */ + Predicate getPredicate(); + + /** + * Retrieves the allowed term type for a specific position. + * + * @param position The position to check (0-based index). + * @return The class type of the allowed term, or null if no constraint. + */ + Class<? extends Term> getTermConstraint(int position); + + /** + * @return An unmodifiable list of positions that are mandatory. + */ + Set<Integer> getMandatoryPositions(); + + /** + * @return An unmodifiable set of indexable position patterns. + */ + Set<Set<Integer>> getIndexablePatterns(); + + /** + * Creates Basic Queries compatible with this atom + * The result can be empty if it is not possible to build a Basic Query + * + * @param positionsAssignation the assignation of the positions + * @return A stream containing the BasicQueries compatible with this termSequence. + */ + Stream<BasicQuery> createQueries(Map<Integer, Term> positionsAssignation); + + /** + * Checks that all mandatory parameters are assigned + * + * @param positionsAssignation the assignation of the positions + * @return true iff the mandatory parameters are assigned + */ + boolean hasAssignedMandatoryParameters(Map<Integer, Term> positionsAssignation); +} \ No newline at end of file diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicPatternBuilder.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AtomicPatternBuilder.java similarity index 60% rename from integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicPatternBuilder.java rename to integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AtomicPatternBuilder.java index 1695e74465fcc17c9393a7cf9c782bcda1c869b4..208dc7c623afcae05e19e964d4276827ab3dddf1 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicPatternBuilder.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/AtomicPatternBuilder.java @@ -1,33 +1,33 @@ package fr.boreal.model.data.readable.query; -import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Predicate; -import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; -import org.apache.commons.lang3.function.TriFunction; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; /** - * Builder class for constructing instances of {@link BasicPattern}. + * Builder class for constructing instances of {@link AtomicPattern}. */ -public class BasicPatternBuilder { +public class AtomicPatternBuilder { private Predicate predicate; - private final List<Integer> mandatoryPositions = new ArrayList<>(); + private final Set<Integer> mandatoryPositions = new HashSet<>(); private final Map<Integer, Class<? extends Term>> termConstraints = new HashMap<>(); - private Function<BasicPattern, Set<Set<Integer>>> indexablePatternsFunction; - private TriFunction<BasicPattern, List<Term>, Substitution, Stream<BasicQuery>> createQueriesFunction; + private Function<AtomicPattern, Set<Set<Integer>>> indexablePatternsFunction; + private BiFunction<AtomicPattern, Map<Integer, Term>, Stream<BasicQuery>> createQueriesFunction; /** - * Sets the predicate for the {@link BasicPattern}. + * Sets the predicate for the {@link AtomicPattern}. * * @param predicate The predicate to be set. * @return The builder instance. */ - public BasicPatternBuilder withPredicate(Predicate predicate) { + public AtomicPatternBuilder withPredicate(Predicate predicate) { this.predicate = predicate; return this; } @@ -38,7 +38,7 @@ public class BasicPatternBuilder { * @param position The position to be added. * @return The builder instance. */ - public BasicPatternBuilder addMandatoryPosition(int position) { + public AtomicPatternBuilder addMandatoryPosition(int position) { this.mandatoryPositions.add(position); return this; } @@ -50,7 +50,7 @@ public class BasicPatternBuilder { * @param termClass The term class allowed at this position. * @return The builder instance. */ - public BasicPatternBuilder addTermConstraint(int position, Class<? extends Term> termClass) { + public AtomicPatternBuilder addTermConstraint(int position, Class<? extends Term> termClass) { this.termConstraints.put(position, termClass); return this; } @@ -61,7 +61,7 @@ public class BasicPatternBuilder { * @param function The function that modifies indexable patterns. * @return The builder instance. */ - public BasicPatternBuilder withIndexablePatternsFunction(Function<BasicPattern, Set<Set<Integer>>> function) { + public AtomicPatternBuilder withIndexablePatternsFunction(Function<AtomicPattern, Set<Set<Integer>>> function) { this.indexablePatternsFunction = function; return this; } @@ -72,17 +72,17 @@ public class BasicPatternBuilder { * @param function The function that generates queries from an Atom. * @return The builder instance. */ - public BasicPatternBuilder withCreateQueriesFunction(TriFunction<BasicPattern, List<Term>, Substitution, Stream<BasicQuery>> function) { + public AtomicPatternBuilder withCreateQueriesFunction(BiFunction<AtomicPattern, Map<Integer, Term>, Stream<BasicQuery>> function) { this.createQueriesFunction = function; return this; } /** - * Builds and returns an instance of {@link BasicPattern}. + * Builds and returns an instance of {@link AtomicPattern}. * - * @return A new {@link BasicPattern} instance. + * @return A new {@link AtomicPattern} instance. */ - public BasicPattern build() { + public AtomicPattern build() { if (predicate == null) { throw new IllegalStateException("Predicate must be set before building."); } @@ -93,15 +93,15 @@ public class BasicPatternBuilder { throw new IllegalStateException("Create queries function must be set before building."); } - return new BasicPattern(predicate, mandatoryPositions, termConstraints) { + return new AbstractAtomicPattern(predicate, mandatoryPositions, termConstraints) { @Override public Set<Set<Integer>> getIndexablePatterns() { return indexablePatternsFunction.apply(this); } @Override - public Stream<BasicQuery> createQueries(List<Term> termSequence, Substitution preHomomorphism) { - return createQueriesFunction.apply(this, termSequence, preHomomorphism); + public Stream<BasicQuery> createQueries(Map<Integer, Term> positionsAssignation) { + return createQueriesFunction.apply(this, positionsAssignation); } }; } diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicPattern.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicPattern.java deleted file mode 100644 index 0beec5311f29ef823cf38eb65cdc54c7bd081623..0000000000000000000000000000000000000000 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicPattern.java +++ /dev/null @@ -1,92 +0,0 @@ -package fr.boreal.model.data.readable.query; - -import fr.boreal.model.logicalElements.api.Atom; -import fr.boreal.model.logicalElements.api.Predicate; -import fr.boreal.model.logicalElements.api.Substitution; -import fr.boreal.model.logicalElements.api.Term; - -import java.util.List; -import java.util.Map; -import java.util.Collections; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -/** - * Represents a basic pattern for querying predicates with specific constraints on term positions. - * This pattern defines which positions must be specified (Mandatory), which can be indexed (Indexable), - * and what types of terms are allowed in each position. - */ -public abstract class BasicPattern { - - private final Predicate predicate; - private final List<Integer> mandatoryPositions; - private final Map<Integer, Class<? extends Term>> termConstraints; - - /** - * Constructs a BasicPattern with specific constraints. - * - * @param predicate The predicate associated with this pattern. - * @param mandatoryPositions A list of positions that are mandatory. - * @param termConstraints A map associating positions (0-based index) with allowed term types. - */ - public BasicPattern(Predicate predicate, List<Integer> mandatoryPositions, - Map<Integer, Class<? extends Term>> termConstraints) { - this.predicate = predicate; - this.mandatoryPositions = Collections.unmodifiableList(mandatoryPositions); - this.termConstraints = Collections.unmodifiableMap(termConstraints); - } - - /** - * @return The predicate associated with this pattern. - */ - public Predicate getPredicate() { - return predicate; - } - - /** - * Retrieves the allowed term type for a specific position. - * - * @param position The position to check (0-based index). - * @return The class type of the allowed term, or null if no constraint. - */ - public Class<? extends Term> getTermConstraint(int position) { - return termConstraints.get(position); - } - - /** - * @return An unmodifiable list of positions that are mandatory. - */ - public List<Integer> getMandatoryPositions() { - return mandatoryPositions; - } - - /** - * @return An unmodifiable set of indexable position patterns. - */ - public abstract Set<Set<Integer>> getIndexablePatterns(); - - /** - * Creates Basic Queries compatible with this atom - * The result can be empty if it is not possible to build a Basic Query - * - * @param termSequence the term sequence to match - * @param preHomomorphism a pre affectation of the variables of termSequence - * @return A stream containing the BasicQueries compatible with this termSequence. - */ - public abstract Stream<BasicQuery> createQueries(List<Term> termSequence, Substitution preHomomorphism); - - /** - * Checks that all mandatory parameters are assigned - * - * @param termSequence the term sequence to check - * @param preHomomorphism a pre affectation of the variables of termSequence - * @return true iff the mandatory parameters are assigned - */ - public boolean hasAssignedMandatoryParameters(List<Term> termSequence, Substitution preHomomorphism) { - return mandatoryPositions.stream().allMatch( - i -> preHomomorphism.createImageOf(termSequence.get(i)).isGround()); - } -} \ No newline at end of file diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicQuery.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicQuery.java index 50d2295500aa42d59793cd2eb940cc74013425ce..a87e0ba1ec6bbc6940e7fc634f681d416f6ed32a 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicQuery.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/readable/query/BasicQuery.java @@ -5,25 +5,24 @@ import fr.boreal.model.logicalElements.api.Predicate; import fr.boreal.model.logicalElements.api.Term; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.Optional; /** - * Represents a query built from a BasicPattern. + * Represents a query built from a AtomicPattern. */ public class BasicQuery { - private final BasicPattern pattern; + private final AtomicPattern pattern; private final Map<Integer, Term> assignedTerms; /** - * Constructs a BasicQuery from a valid BasicPattern. + * Constructs a BasicQuery from a valid AtomicPattern. * - * @param pattern The BasicPattern that defines the query structure. + * @param pattern The AtomicPattern that defines the query structure. * @param assignedTerms The terms assigned to specific positions. */ - public BasicQuery(BasicPattern pattern, Map<Integer, Term> assignedTerms) { + public BasicQuery(AtomicPattern pattern, Map<Integer, Term> assignedTerms) { this.pattern = pattern; this.assignedTerms = Collections.unmodifiableMap(assignedTerms); } diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/data/writable/Writable.java b/integraal/integraal-model/src/main/java/fr/boreal/model/data/writable/Writable.java index cbdf8916098a93ff788764524b63bb3558d5b49d..17b9df6f4a782ad94764b6e3ab3f62e8cf4fecc7 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/data/writable/Writable.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/data/writable/Writable.java @@ -26,7 +26,9 @@ public interface Writable { * @param atoms to add * @return true iff at least one atom is new */ - boolean add(FOFormula atoms); + default boolean add(FOFormula atoms) { + return addAll(atoms.asAtomSet()); + } /** * Stores the given atoms @@ -34,7 +36,9 @@ public interface Writable { * @param atoms to add * @return true iff at least one atom is new */ - boolean addAll(Collection<Atom> atoms); + default boolean addAll(Collection<Atom> atoms) { + return addAll(atoms.stream()); + } /** * Stores the given atoms @@ -60,7 +64,9 @@ public interface Writable { * @param atoms to remove * @return true iff at least one atom is removed */ - boolean remove(FOFormula atoms); + default boolean remove(FOFormula atoms) { + return removeAll(atoms.asAtomSet()); + } /** * Removes the given atoms @@ -68,7 +74,9 @@ public interface Writable { * @param atoms to remove * @return true iff at least one atom is removed */ - boolean removeAll(Collection<Atom> atoms); + default boolean removeAll(Collection<Atom> atoms) { + return removeAll(atoms.stream()); + } /** * Removes the given atoms diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityConstantImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityConstantImpl.java index 8403de81093737ec437e6df96f8a7429fd03d308..1666f14f84adecc607e93dda8d8cfee9881774c6 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityConstantImpl.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityConstantImpl.java @@ -9,10 +9,19 @@ import fr.boreal.model.logicalElements.api.Constant; * * @author Florent Tornil */ -public record IdentityConstantImpl(String label) implements Constant { +public final class IdentityConstantImpl extends IdentityTermImpl implements Constant { + private final String label; - @Override - public String toString() { - return this.label; - } + /** + * Constructor using a label + * @param label string representation + */ + public IdentityConstantImpl(String label) { + this.label = label; + } + + @Override + public String label() { + return label; + } } diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityFreshVariableImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityFreshVariableImpl.java index c036fdac58faff52069789575fb7ebb23c860aa3..0db9850442a35a63fdd25913bd5fafffd11c835a 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityFreshVariableImpl.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityFreshVariableImpl.java @@ -9,11 +9,6 @@ package fr.boreal.model.logicalElements.impl.identityObjects; * */ public class IdentityFreshVariableImpl extends IdentityVariableImpl { - - ///////////////////////////////////////////////// - // Constructors - ///////////////////////////////////////////////// - /** * Constructor using a label * @param label string representation @@ -21,5 +16,4 @@ public class IdentityFreshVariableImpl extends IdentityVariableImpl { public IdentityFreshVariableImpl(String label) { super(label); } - } diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityLiteralImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityLiteralImpl.java index b1c30621c9ee8941a85dac332dc8adc5f46c36c1..a7d304c4e8525a2d325fdf6a72d0cb3608fddc7e 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityLiteralImpl.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityLiteralImpl.java @@ -10,22 +10,25 @@ import fr.boreal.model.logicalElements.api.Literal; * @param <T> the native type of the Literal * @author Florent Tornil */ -public record IdentityLiteralImpl<T>(T value) implements Literal<T> { +public class IdentityLiteralImpl<T> extends IdentityTermImpl implements Literal<T> { - @Override - public String label() { - return this.value.toString(); + private final T value; + + /** + * Constructor using a label + * @param value the value contained in the literal + */ + public IdentityLiteralImpl(T value) { + this.value = value; } @Override - public String toString() { + public String label() { return this.value == null ? "null" : this.value.toString(); } - public boolean equals(Object o){ - if (this == o) { - return true; - }; - return false; + @Override + public T value() { + return value; } } diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityPredicateImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityPredicateImpl.java index f98413d3e3b3230d9f038333d6984918eecda5dd..992111dea4da4a2ab5362ed1813f47ae7d42f022 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityPredicateImpl.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityPredicateImpl.java @@ -10,10 +10,24 @@ import fr.boreal.model.logicalElements.api.Predicate; * @author Florent Tornil */ public record IdentityPredicateImpl(String label, int arity) implements Predicate { - @Override public String toString() { return this.label; } + @Override + public boolean equals(Object obj) { + if (obj instanceof IdentityPredicateImpl) { + return this == obj; // Reference equality + } else { + // Use the equals method of the other object to do the comparison + // This ensures that the comparison with non-identity objects will work + return obj != null && obj.equals(this); + } + } + + @Override + public int hashCode() { + return System.identityHashCode(this); // Ensures consistency with equals() + } } diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityTermImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityTermImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..b8ab0a02a81a448f6094b220f03615449959d03a --- /dev/null +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityTermImpl.java @@ -0,0 +1,27 @@ +package fr.boreal.model.logicalElements.impl.identityObjects; + +import fr.boreal.model.logicalElements.api.Term; + +public abstract class IdentityTermImpl implements Term { + + @Override + public boolean equals(Object obj) { + if (obj instanceof IdentityTermImpl) { + return this == obj; // Reference equality + } else { + // Use the equals method of the other object to do the comparison + // This ensures that the comparison with non-identity objects will work + return obj != null && obj.equals(this); + } + } + + @Override + public int hashCode() { + return System.identityHashCode(this); // Ensures consistency with equals() + } + + @Override + public String toString() { + return this.label(); + } +} diff --git a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityVariableImpl.java b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityVariableImpl.java index 03e9d63ce0ab5faf48106dd65dcef594c842aa81..0693a02e20d9fee07bbf1c634ef300b3d39f64ca 100644 --- a/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityVariableImpl.java +++ b/integraal/integraal-model/src/main/java/fr/boreal/model/logicalElements/impl/identityObjects/IdentityVariableImpl.java @@ -10,7 +10,7 @@ import fr.boreal.model.logicalElements.api.Variable; * @author Florent Tornil * */ -public class IdentityVariableImpl implements Variable { +public class IdentityVariableImpl extends IdentityTermImpl implements Variable { private final String label; @@ -26,9 +26,4 @@ public class IdentityVariableImpl implements Variable { public String label() { return this.label; } - - @Override - public String toString() { - return this.label; - } } diff --git a/integraal/integraal-model/src/main/java/module-info.java b/integraal/integraal-model/src/main/java/module-info.java index 4ab7c5ff528f453ad59344beb3021f4b0d88f0d8..3e96aac276c7337426f36fbdb7cc93b078df4d8b 100644 --- a/integraal/integraal-model/src/main/java/module-info.java +++ b/integraal/integraal-model/src/main/java/module-info.java @@ -14,7 +14,11 @@ module fr.boreal.model { requires com.google.errorprone.annotations; requires jdk.jdi; // Java compiler for the unary tests + exports fr.boreal.model.data.collection.api; + exports fr.boreal.model.data.collection.builder; exports fr.boreal.model.data.readable; + exports fr.boreal.model.data.readable.query; + exports fr.boreal.model.data.readable.exception; exports fr.boreal.model.data.writable; exports fr.boreal.model.logicalElements.api; @@ -45,7 +49,5 @@ module fr.boreal.model { exports fr.boreal.model.ruleCompilation.api; exports fr.boreal.model.ruleCompilation.id; exports fr.boreal.model.logicalElements.impl.functionalTerms; - exports fr.boreal.model.data.readable.query; - exports fr.boreal.model.data.readable.exception; } \ No newline at end of file diff --git a/integraal/integraal-model/src/test/java/fr/boreal/test/model/terms/TermEqualityTest.java b/integraal/integraal-model/src/test/java/fr/boreal/test/model/terms/TermEqualityTest.java new file mode 100644 index 0000000000000000000000000000000000000000..663c98ecd053f3ef757e4979ad1ccbbbf93bc95d --- /dev/null +++ b/integraal/integraal-model/src/test/java/fr/boreal/test/model/terms/TermEqualityTest.java @@ -0,0 +1,63 @@ +package fr.boreal.test.model.terms; + +import fr.boreal.model.logicalElements.api.Constant; +import fr.boreal.model.logicalElements.api.Literal; +import fr.boreal.model.logicalElements.api.Term; +import fr.boreal.model.logicalElements.api.Variable; +import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; +import fr.boreal.model.logicalElements.impl.ConstantImpl; +import fr.boreal.model.logicalElements.impl.LiteralImpl; +import fr.boreal.model.logicalElements.impl.VariableImpl; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class TermEqualityTest { + @Test + public void testEquality() { + Variable varNonIdentity = new VariableImpl("term"); + Variable varIdentity = SameObjectTermFactory.instance().createOrGetVariable("term");; + Variable varIdentity2 = SameObjectTermFactory.instance().createOrGetVariable("term"); + List<Variable> variables = List.of(varNonIdentity, varIdentity, varIdentity2); + + assertAllEquals(variables); + + Constant constNonIdentity = new ConstantImpl("term"); + Constant constIdentity = SameObjectTermFactory.instance().createOrGetConstant("term");; + Constant constIdentity2 = SameObjectTermFactory.instance().createOrGetConstant("term"); + List<Constant> constants = List.of(constNonIdentity, constIdentity, constIdentity2); + + assertAllEquals(constants); + assertNotEquals(constants, variables); + + Literal<String> litNonIdentity = new LiteralImpl<>("term"); + Literal<String> litIdentity = SameObjectTermFactory.instance().createOrGetLiteral("term");; + Literal<String> litIdentity2 = SameObjectTermFactory.instance().createOrGetLiteral("term"); + List<Literal<String>> literals = List.of(litNonIdentity, litIdentity, litIdentity2); + + assertAllEquals(literals); + assertNotEquals(literals, variables, constants); + } + + private void assertAllEquals(Collection<?> collection) { + collection.forEach(o1 -> + collection.forEach(o2 -> { + Assertions.assertEquals(o1, o2); + Assertions.assertEquals(o2, o1); + })); + } + + private void assertNotEquals(Collection<?> collection, Collection<?> ...otherCollections) { + for (Collection<?> collection2 : otherCollections) { + for (Object o1 : collection) { + for (Object o2 : collection2) { + Assertions.assertNotEquals(o1, o2); + Assertions.assertNotEquals(o2, o1); + } + } + } + } +} diff --git a/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/atomic/AtomicFOQueryEvaluator.java b/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/atomic/AtomicFOQueryEvaluator.java index 7a62fcd9dca51734de9d4ad0fc3de978e26f1f04..d3c5f9dfca313a6cddfb99d71d70bb021582896e 100644 --- a/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/atomic/AtomicFOQueryEvaluator.java +++ b/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/atomic/AtomicFOQueryEvaluator.java @@ -2,7 +2,7 @@ package fr.boreal.query_evaluation.atomic; import fr.boreal.model.data.readable.QueryableData; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; +import fr.boreal.model.data.readable.query.AtomicPattern; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.*; import fr.boreal.model.logicalElements.impl.AtomImpl; @@ -11,8 +11,8 @@ import fr.boreal.model.partition.TermPartition; import fr.boreal.model.query.api.FOQuery; import fr.boreal.model.queryEvaluation.api.FOQueryEvaluator; import fr.boreal.query_evaluation.utils.filters.GroundTermAtPositionFilter; +import fr.boreal.query_evaluation.utils.filters.PositionsAssignationFilter; import fr.boreal.query_evaluation.utils.transformers.TermSequenceToSubstitutionTransformer; -import org.apache.commons.lang3.tuple.Pair; import java.util.*; import java.util.stream.Collectors; @@ -31,7 +31,11 @@ public class AtomicFOQueryEvaluator<QD extends QueryableData> implements FOQuery ///////////////////////////////////////////////// @Override - public Stream<Substitution> evaluate(FOQuery<? extends Atom> query, QD queryableData, Collection<Variable> vars, Substitution preHomomorphism) throws EvaluationException { + public Stream<Substitution> evaluate( + FOQuery<? extends Atom> query, + QD queryableData, + Collection<Variable> vars, + Substitution preHomomorphism) throws EvaluationException { Atom atom = query.getFormula(); if (!query.getVariableEqualities().getElements().isEmpty()) { @@ -44,6 +48,7 @@ public class AtomicFOQueryEvaluator<QD extends QueryableData> implements FOQuery } Stream<List<Term>> stream = null; + if (atom instanceof ComputedAtom ca && ca.isEvaluableWith(preHomomorphism)) { Atom result = ca.eval(preHomomorphism); if (ca.getPredicate().equals(Predicate.TOP)) { @@ -61,13 +66,22 @@ public class AtomicFOQueryEvaluator<QD extends QueryableData> implements FOQuery } else { return t; }}).toList()); - BasicQuery bq = selectBasicQuery(queryableData, atom, preHomomorphism).orElseThrow( + + Map<Integer, Term> positionsAffectation = computePositionsAssignation(atom, preHomomorphism); + BasicQuery bq = selectBasicQuery(queryableData, atom.getPredicate(), positionsAffectation).orElseThrow( () -> new EvaluationException(String.format( "The query %s is unsupported by the QueryableData %s", query, queryableData.getClass().getSimpleName()) )); // TODO: improve the exception so that it is more informative - stream = queryableData.evaluate(bq); + stream = queryableData.evaluate(bq) + .filter(new PositionsAssignationFilter( // Filter values with the assignation + positionsAffectation.keySet().stream() + // We don't need to filter by the values that were already in the query + .filter(i -> !bq.getAssignedTerms().containsKey(i)) + .map(i -> Map.entry(i, positionsAffectation.get(i))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) + )); } if (!vars.isEmpty()) { @@ -81,6 +95,23 @@ public class AtomicFOQueryEvaluator<QD extends QueryableData> implements FOQuery .map(s -> makeSubstitutionOnAnswerVariables(s, query.getAnswerVariables(), query.getVariableEqualities())); } + private Map<Integer, Term> computePositionsAssignation( + Atom atom, + Substitution preHomomorphism) { + Map<Integer, Term> positions = new HashMap<>(); + + for (int i = 0; i < atom.getTermSequence().size(); i++) { + Term t = atom.getTermSequence().get(i); + if (t.isGround()) { + positions.put(i, t); + } else if (preHomomorphism.keys().contains(t)) { + positions.put(i, preHomomorphism.createImageOf(t)); + } + } + + return positions; + } + private static Substitution makeSubstitutionOnAnswerVariables ( Substitution result, Collection<Variable> answerVariables, @@ -100,14 +131,14 @@ public class AtomicFOQueryEvaluator<QD extends QueryableData> implements FOQuery private static Optional<BasicQuery> selectBasicQuery( QueryableData queryableData, - Atom atom, - Substitution preHomomorphism) { + Predicate predicate, + Map<Integer, Term> positionsAffectation) { long minBound = Long.MAX_VALUE; - BasicPattern basicPattern = queryableData.getBasicPattern(atom.getPredicate()); + AtomicPattern atomicPattern = queryableData.getBasicPattern(predicate); BasicQuery best = null; for (BasicQuery bq: (Iterable<BasicQuery>) - basicPattern.createQueries(atom.getTermSequence(), preHomomorphism)::iterator) { + atomicPattern.createQueries(positionsAffectation)::iterator) { Optional<Long> estimation = queryableData.estimateBound(bq); if (estimation.isPresent()) { if (estimation.get() < minBound) { diff --git a/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/generic/GenericFOQueryEvaluator.java b/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/generic/GenericFOQueryEvaluator.java index f6d97ea55009adeceb321f5b998412c65607f534..6f52569a508de2a3e1fd1dae44f1722fd4c8cbb4 100644 --- a/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/generic/GenericFOQueryEvaluator.java +++ b/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/generic/GenericFOQueryEvaluator.java @@ -44,9 +44,9 @@ public class GenericFOQueryEvaluator<QD extends QueryableData> implements FOQuer * one doesn't want to configure it. * @return the default instance of the evaluator */ - public static GenericFOQueryEvaluator<QueryableData> defaultInstance() { - GenericFOQueryEvaluator<QueryableData> instance = new GenericFOQueryEvaluator<>(); - return instance.setAtomicEvaluator(new AtomicFOQueryEvaluator()) + public static <QD extends QueryableData> GenericFOQueryEvaluator<QD> defaultInstance() { + GenericFOQueryEvaluator<QD> instance = new GenericFOQueryEvaluator<>(); + return instance.setAtomicEvaluator(new AtomicFOQueryEvaluator<>()) .setConjunctionEvaluator(new BacktrackEvaluator<>(instance)) .setNegationEvaluator(new NegationFOQueryEvaluator<>(instance)); } @@ -56,9 +56,11 @@ public class GenericFOQueryEvaluator<QD extends QueryableData> implements FOQuer * @return an instance of the evaluator using compilation with unfold evaluation * strategy */ - public static GenericFOQueryEvaluator<QueryableData> defaultInstanceWithUnfoldCompilation(RuleCompilation compilation) { - GenericFOQueryEvaluator<QueryableData> instance = GenericFOQueryEvaluator.defaultInstance(); - return instance.setAtomicEvaluator(new UnfoldingAtomicFOQueryEvaluator(compilation)) + public static <QD extends QueryableData> + GenericFOQueryEvaluator<QD> defaultInstanceWithUnfoldCompilation(RuleCompilation compilation) { + GenericFOQueryEvaluator<QD> instance = + GenericFOQueryEvaluator.defaultInstance(); + return instance.setAtomicEvaluator(new UnfoldingAtomicFOQueryEvaluator<>(compilation)) .setConjunctionEvaluator(new BacktrackEvaluator<>(instance)) .setNegationEvaluator(new NegationFOQueryEvaluator<>(instance)); } diff --git a/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/utils/filters/PositionsAssignationFilter.java b/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/utils/filters/PositionsAssignationFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..9e3163d8aaac2fa9f666d8c324f2f3b0f4778cd4 --- /dev/null +++ b/integraal/integraal-query-evaluation/src/main/java/fr/boreal/query_evaluation/utils/filters/PositionsAssignationFilter.java @@ -0,0 +1,21 @@ +package fr.boreal.query_evaluation.utils.filters; + +import fr.boreal.model.logicalElements.api.Term; + +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +public class PositionsAssignationFilter implements Predicate<List<Term>> { + private final Map<Integer, Term> positionsAssignation; + + public PositionsAssignationFilter(Map<Integer, Term> positionsAssignation) { + this.positionsAssignation = positionsAssignation; + } + + @Override + public boolean test(List<Term> terms) { + return positionsAssignation.keySet().stream() + .allMatch(position -> positionsAssignation.get(position).equals(terms.get(position))); + } +} diff --git a/integraal/integraal-query-evaluation/src/test/java/fr/boreal/test/query_evaluation/AtomicFOQueryEvaluatorBenchmark.java b/integraal/integraal-query-evaluation/src/test/java/fr/boreal/test/query_evaluation/AtomicFOQueryEvaluatorBenchmark.java index ff7f97b3c999102d54cb70084984bd748af0816b..07a0062ee53c5930bfbefa924031ab446bf694f8 100644 --- a/integraal/integraal-query-evaluation/src/test/java/fr/boreal/test/query_evaluation/AtomicFOQueryEvaluatorBenchmark.java +++ b/integraal/integraal-query-evaluation/src/test/java/fr/boreal/test/query_evaluation/AtomicFOQueryEvaluatorBenchmark.java @@ -13,7 +13,9 @@ import fr.boreal.model.queryEvaluation.api.FOQueryEvaluator; import fr.boreal.query_evaluation.atomic.AtomicFOQueryEvaluator; import fr.boreal.storage.natives.SimpleInMemoryGraphStore; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -27,21 +29,34 @@ public class AtomicFOQueryEvaluatorBenchmark { null ); FOQueryEvaluator<Atom, MaterializedData> evaluator = new AtomicFOQueryEvaluator<>(); + long start, end; + List<Long> times = new ArrayList<>(); // Sequential execution benchmark - long start = System.nanoTime(); - System.out.println(evaluator.evaluate(query, factBase, Set.of(TestData.x), new fr.boreal.model.logicalElements.impl.SubstitutionImpl()) - .collect(Collectors.toSet())); - long end = System.nanoTime(); - System.out.println("Sequential execution time: " + (end - start) / 1_000_000 + " ms"); + for (int i = 0; i < 1000; i++) { + start = System.nanoTime(); + //System.out.println( + evaluator.evaluate(query, factBase, Set.of(TestData.x), new fr.boreal.model.logicalElements.impl.SubstitutionImpl()) + .collect(Collectors.toSet()); + end = System.nanoTime(); + times.add(end - start); + //System.out.println("Sequential execution time: " + (end - start) / 1_000_000 + " ms"); + } + System.out.println("Sequential execution time: " + times.stream().mapToLong(i -> i).average().getAsDouble() / 1_000_000L + " ms"); + times.clear(); // Parallel execution benchmark - start = System.nanoTime(); - System.out.println(evaluator.evaluate(query, factBase, Set.of(TestData.x), new fr.boreal.model.logicalElements.impl.SubstitutionImpl()) - .parallel() - .collect(Collectors.toSet())); - end = System.nanoTime(); - System.out.println("Parallel execution time: " + (end - start) / 1_000_000 + " ms"); + for (int i = 0; i < 1000; i++) { + start = System.nanoTime(); + //System.out.println( + evaluator.evaluate(query, factBase, Set.of(TestData.x), new fr.boreal.model.logicalElements.impl.SubstitutionImpl()) + .parallel() + .collect(Collectors.toSet()); + end = System.nanoTime(); + times.add(end - start); + //System.out.println("Parallel execution time: " + (end - start) / 1_000_000 + " ms"); + } + System.out.println("Parallel execution time: " + times.stream().mapToLong(i -> i).average().getAsDouble() / 1_000_000L + " ms"); } private static FactBase generateFactBase() { diff --git a/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/rdbms/RDBMSStore.java b/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/rdbms/RDBMSStore.java index cbc49e119ff45ece9d707817814ff7e2a77eeeb0..15a29c77625ad891ece45a4a5d8b3d6829380fa7 100644 --- a/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/rdbms/RDBMSStore.java +++ b/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/rdbms/RDBMSStore.java @@ -4,8 +4,8 @@ import com.github.jsonldjava.shaded.com.google.common.collect.Sets; import fr.boreal.model.data.readable.DatalogDelegable; import fr.boreal.model.data.readable.QueryDelegatableData; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; -import fr.boreal.model.data.readable.query.BasicPatternBuilder; +import fr.boreal.model.data.readable.query.AtomicPattern; +import fr.boreal.model.data.readable.query.AtomicPatternBuilder; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.formula.api.FOFormulaConjunction; @@ -102,18 +102,13 @@ public class RDBMSStore implements FactBase, QueryDelegatableData, DatalogDelega } @Override - public BasicPattern getBasicPattern(Predicate predicate) { - BasicPatternBuilder bpb = new BasicPatternBuilder().withPredicate(predicate); + public AtomicPattern getBasicPattern(Predicate predicate) { + AtomicPatternBuilder bpb = new AtomicPatternBuilder().withPredicate(predicate); bpb.withIndexablePatternsFunction(basicPattern -> Sets.powerSet(IntStream.range(0, predicate.arity()).boxed().collect(Collectors.toSet()))); - bpb.withCreateQueriesFunction((basicPattern, termSequence, preHomomorphism) -> - Stream.of(new BasicQuery(basicPattern, IntStream.range(0, predicate.arity()).boxed() - .filter(i -> termSequence.get(i).isGround() - || preHomomorphism.keys().contains(termSequence.get(i))) - .map(i -> Map.entry(i, preHomomorphism.createImageOf(termSequence.get(i)))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) - ))); + bpb.withCreateQueriesFunction((basicPattern, positionsAssignation) -> + Stream.of(new BasicQuery(basicPattern, positionsAssignation))); return bpb.build(); } diff --git a/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/triplestore/TripleStoreStore.java b/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/triplestore/TripleStoreStore.java index 6ff4d9fa6ecafeff546929c88d39ff7539b69001..08ca1f70ef2401c857890a56bc292467e531e8d7 100644 --- a/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/triplestore/TripleStoreStore.java +++ b/integraal/integraal-storage/src/main/java/fr/boreal/storage/external/triplestore/TripleStoreStore.java @@ -2,8 +2,8 @@ package fr.boreal.storage.external.triplestore; import com.github.jsonldjava.shaded.com.google.common.collect.Sets; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; -import fr.boreal.model.data.readable.query.BasicPatternBuilder; +import fr.boreal.model.data.readable.query.AtomicPattern; +import fr.boreal.model.data.readable.query.AtomicPatternBuilder; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.formula.api.FOFormulaConjunction; @@ -22,12 +22,9 @@ import fr.boreal.model.query.api.FOQuery; import fr.boreal.model.query.factory.FOQueryFactory; import fr.boreal.model.rule.api.FORule; import fr.boreal.storage.external.evaluator.SparqlQueryEvaluator; -import fr.lirmm.boreal.util.stream.filter.FilterIteratorWithoutException; -import fr.lirmm.boreal.util.stream.filter.MatchFilter; import fr.lirmm.boreal.util.validator.rule.ConjunctionFormulaValidator; import fr.lirmm.boreal.util.validator.rule.PositiveFormulaValidator; import org.apache.commons.lang3.NotImplementedException; -import org.checkerframework.checker.units.qual.C; import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.*; import org.eclipse.rdf4j.query.TupleQueryResult; @@ -168,22 +165,17 @@ public class TripleStoreStore implements FactBase, DatalogDelegable { } @Override - public BasicPattern getBasicPattern(Predicate predicate) { - BasicPatternBuilder bpb = new BasicPatternBuilder().withPredicate(predicate); + public AtomicPattern getBasicPattern(Predicate predicate) { + AtomicPatternBuilder bpb = new AtomicPatternBuilder().withPredicate(predicate); if(predicate.arity() > 2) { // No supported pattern for predicates with a too big arity bpb.withIndexablePatternsFunction(basicPattern -> Set.of()); - bpb.withCreateQueriesFunction((basicPattern, termSequence, preHomomorphism) -> Stream.of()); + bpb.withCreateQueriesFunction((basicPattern, positionsAssignation) -> Stream.of()); } else { bpb.withIndexablePatternsFunction(basicPattern -> Sets.powerSet(IntStream.range(0, predicate.arity()).boxed().collect(Collectors.toSet()))); - bpb.withCreateQueriesFunction((basicPattern, termSequence, preHomomorphism) -> - Stream.of(new BasicQuery(basicPattern, IntStream.range(0, predicate.arity()).boxed() - .filter(i -> termSequence.get(i).isGround() - || preHomomorphism.keys().contains(termSequence.get(i))) - .map(i -> Map.entry(i, preHomomorphism.createImageOf(termSequence.get(i)))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) - ))); + bpb.withCreateQueriesFunction((basicPattern, positionsAssignation) -> + Stream.of(new BasicQuery(basicPattern, positionsAssignation))); } return bpb.build(); diff --git a/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/DefaultInMemoryAtomSet.java b/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/DefaultInMemoryAtomSet.java index 79a39f62c9c9615128789d0763748cce022af89a..acc7344a04b6ee71a639322dcb3fed590d98adf1 100644 --- a/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/DefaultInMemoryAtomSet.java +++ b/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/DefaultInMemoryAtomSet.java @@ -4,18 +4,14 @@ package fr.boreal.storage.natives; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; -import fr.boreal.model.data.readable.query.BasicPatternBuilder; +import fr.boreal.model.data.readable.query.AtomicPattern; +import fr.boreal.model.data.readable.query.AtomicPatternBuilder; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.kb.api.FactBaseType; import fr.boreal.model.kb.impl.FactBaseDescription; import fr.boreal.model.logicalElements.api.*; -import fr.boreal.model.logicalElements.impl.SubstitutionImpl; -import fr.lirmm.boreal.util.AtomType; -import fr.lirmm.boreal.util.stream.filter.FilterIteratorWithoutException; -import fr.lirmm.boreal.util.stream.filter.TypeFilter; import java.util.*; import java.util.stream.Collectors; @@ -89,11 +85,11 @@ public class DefaultInMemoryAtomSet implements FactBase { } @Override - public BasicPattern getBasicPattern(Predicate predicate) { - BasicPatternBuilder builder = new BasicPatternBuilder().withPredicate(predicate); + public AtomicPattern getBasicPattern(Predicate predicate) { + AtomicPatternBuilder builder = new AtomicPatternBuilder().withPredicate(predicate); builder.withIndexablePatternsFunction(basicPattern -> (Set<Set<Integer>>) Stream.of(Set.of())); builder.withCreateQueriesFunction( - (basicPattern, termSequence, preHomomorphism) -> Stream.of(new BasicQuery(basicPattern, Map.of()))); + (basicPattern, positionsAssignation) -> Stream.of(new BasicQuery(basicPattern, Map.of()))); return builder.build(); } diff --git a/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/FactBaseDelAtomsWrapper.java b/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/FactBaseDelAtomsWrapper.java index 74dedb2f0429d0bad290e83df153bffcd33526b0..950a4f7a7f71aa66e3e58fdd5ba298b0fc3f0f38 100644 --- a/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/FactBaseDelAtomsWrapper.java +++ b/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/FactBaseDelAtomsWrapper.java @@ -1,7 +1,7 @@ package fr.boreal.storage.natives; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; +import fr.boreal.model.data.readable.query.AtomicPattern; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.ColumnType; @@ -167,7 +167,7 @@ public class FactBaseDelAtomsWrapper implements FactBase { } @Override - public BasicPattern getBasicPattern(Predicate predicate) { + public AtomicPattern getBasicPattern(Predicate predicate) { return this.factBase.getBasicPattern(predicate); } diff --git a/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/SimpleInMemoryGraphStore.java b/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/SimpleInMemoryGraphStore.java index 50b81c3a755b1e63da32d66c3be245de9a8dc6ca..a88418fd372599c7617121af03633a0b8f228999 100644 --- a/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/SimpleInMemoryGraphStore.java +++ b/integraal/integraal-storage/src/main/java/fr/boreal/storage/natives/SimpleInMemoryGraphStore.java @@ -1,22 +1,14 @@ package fr.boreal.storage.natives; -import com.google.common.collect.Sets; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; -import fr.boreal.model.data.readable.query.BasicPatternBuilder; +import fr.boreal.model.data.readable.query.AtomicPattern; +import fr.boreal.model.data.readable.query.AtomicPatternBuilder; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; import fr.boreal.model.kb.api.FactBaseType; import fr.boreal.model.kb.impl.FactBaseDescription; import fr.boreal.model.logicalElements.api.*; -import fr.boreal.model.logicalElements.impl.SubstitutionImpl; -import fr.boreal.model.query.api.Query; -import fr.lirmm.boreal.util.AtomType; -import fr.lirmm.boreal.util.stream.CloseableIteratorAdapter; -import fr.lirmm.boreal.util.stream.CloseableIteratorWithoutException; -import fr.lirmm.boreal.util.stream.filter.FilterIteratorWithoutException; -import fr.lirmm.boreal.util.stream.filter.TypeFilter; import fr.lirmm.boreal.util.validator.rule.ConjunctionFormulaValidator; import fr.lirmm.boreal.util.validator.rule.PositiveFormulaValidator; @@ -347,18 +339,16 @@ public class SimpleInMemoryGraphStore implements FactBase { } @Override - public BasicPattern getBasicPattern(Predicate predicate) { - BasicPatternBuilder bpb = new BasicPatternBuilder().withPredicate(predicate); + public AtomicPattern getBasicPattern(Predicate predicate) { + AtomicPatternBuilder bpb = new AtomicPatternBuilder().withPredicate(predicate); bpb.withIndexablePatternsFunction(basicPattern -> Stream.concat( Stream.of(new HashSet<Integer>()), IntStream.range(0, predicate.arity()).boxed().map(Set::of)) .collect(Collectors.toSet())); - bpb.withCreateQueriesFunction((basicPattern, termSequence, preHomomorphism) -> + bpb.withCreateQueriesFunction((basicPattern, positionsAssignation) -> Stream.concat(Stream.of(new BasicQuery(basicPattern, Map.of())), - IntStream.range(0, predicate.arity()).boxed() - .filter(i -> termSequence.get(i).isGround() - || preHomomorphism.keys().contains(termSequence.get(i))) - .map(i -> Map.of(i, preHomomorphism.createImageOf(termSequence.get(i)))) + positionsAssignation.keySet().stream() + .map(i -> Map.of(i, positionsAssignation.get(i))) .map(assignation -> new BasicQuery(basicPattern, assignation)) )); diff --git a/integraal/integraal-storage/src/test/java/fr/boreal/test/storage/FactBaseCommonTests.java b/integraal/integraal-storage/src/test/java/fr/boreal/test/storage/FactBaseCommonTests.java index 775d03bf68611f2af588acf0486a203648379122..ea757d302fe37fe2a07fc837b7baa7c3c1d800cb 100644 --- a/integraal/integraal-storage/src/test/java/fr/boreal/test/storage/FactBaseCommonTests.java +++ b/integraal/integraal-storage/src/test/java/fr/boreal/test/storage/FactBaseCommonTests.java @@ -1,7 +1,7 @@ package fr.boreal.test.storage; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; +import fr.boreal.model.data.readable.query.AtomicPattern; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.formula.api.FOFormulaConjunction; import fr.boreal.model.formula.factory.FOFormulaFactory; @@ -19,6 +19,7 @@ import org.junit.jupiter.params.provider.MethodSource; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; // TODO: this class was quickly adapted from the tests for FactBaseDelAtomsWrapper, more test cases should be added @@ -659,12 +660,17 @@ public class FactBaseCommonTests { @MethodSource("provideFactBases") public void testEvaluate(FactBase base) throws EvaluationException { for (Atom a: base) { - BasicPattern basicPattern = base.getBasicPattern(a.getPredicate()); - if (!basicPattern.hasAssignedMandatoryParameters(a.getTermSequence(), new SubstitutionImpl())) { + AtomicPattern atomicPattern = base.getBasicPattern(a.getPredicate()); + Map<Integer, Term> positions = IntStream.range(0, a.getTermSequence().size()).boxed() + .filter(i -> a.getTerm(i).isGround()) + .map(i -> Map.entry(i, a.getTerm(i))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + if (!atomicPattern.hasAssignedMandatoryParameters(positions)) { continue; } - Collection<BasicQuery> queries = basicPattern.createQueries(a.getTermSequence(), new SubstitutionImpl()) + Collection<BasicQuery> queries = atomicPattern.createQueries(positions) .toList(); Assertions.assertFalse(queries.isEmpty()); diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/FederatedFactBase.java b/integraal/integraal-views/src/main/java/fr/boreal/views/FederatedFactBase.java index b81c6b9c07fb11dd1c04b665b27d0337d29ecddb..d55a108f8bafc77c71229c0b2de77d4b2ac4f24b 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/FederatedFactBase.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/FederatedFactBase.java @@ -1,10 +1,8 @@ package fr.boreal.views; -import com.google.common.collect.Iterators; import fr.boreal.model.data.readable.QueryableData; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; -import fr.boreal.model.data.readable.query.BasicPatternBuilder; +import fr.boreal.model.data.readable.query.AtomicPattern; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.formula.api.FOFormula; import fr.boreal.model.kb.api.FactBase; @@ -12,9 +10,8 @@ import fr.boreal.model.kb.api.FactBaseType; import fr.boreal.model.kb.impl.FactBaseDescription; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Predicate; -import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; -import fr.boreal.views.datasource.AbstractViewWrapper; +import fr.boreal.views.datasource.DataSource; import java.util.*; import java.util.stream.Collectors; @@ -28,6 +25,7 @@ import java.util.stream.Stream; * @author Florent Tornil * */ +@Deprecated public class FederatedFactBase implements FactBase { private final Map<Predicate, QueryableData> facts_by_storage; @@ -64,9 +62,9 @@ public class FederatedFactBase implements FactBase { * @param default_base the default storage in writing mode * @param views the views */ - public FederatedFactBase(FactBase default_base, Collection<AbstractViewWrapper<String, ?>> views) { + public FederatedFactBase(FactBase default_base, Collection<DataSource<String, ?>> views) { this(default_base); - for (AbstractViewWrapper<String, ?> view : views) { + for (DataSource<String, ?> view : views) { for (Iterator<Predicate> it = view.getPredicates().iterator(); it.hasNext(); ) { Predicate p = it.next(); this.addStorage(p, view); @@ -203,7 +201,7 @@ public class FederatedFactBase implements FactBase { } @Override - public BasicPattern getBasicPattern(Predicate predicate) { + public AtomicPattern getBasicPattern(Predicate predicate) { return this.chooseStorage(predicate).getBasicPattern(predicate); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/builder/ViewBuilder.java b/integraal/integraal-views/src/main/java/fr/boreal/views/builder/ViewBuilder.java index 7ca63f762eadd0a993465328829025c2e9b4a5b9..ed09ed3be103085f2989062b889cfe49b6925b5f 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/builder/ViewBuilder.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/builder/ViewBuilder.java @@ -8,6 +8,8 @@ import fr.boreal.storage.external.rdbms.driver.MySQLDriver; import fr.boreal.storage.external.rdbms.driver.PostgreSQLDriver; import fr.boreal.storage.external.rdbms.driver.SQLiteDriver; import fr.boreal.views.datasource.*; +import fr.boreal.views.view.ViewParameterSignature; +import fr.boreal.views.view.ViewParameters; import fr.inria.integraal.view_parser.parser.*; import java.io.FileNotFoundException; @@ -27,7 +29,7 @@ import java.util.Optional; */ public class ViewBuilder { - private AbstractViewWrapper<String, ?> source; + private AbstractDataSource<String, ?> source; private final List<ViewRegistration> views = new ArrayList<>(); private static final PredicateFactory pf = FactoryConstants.DEFAULT_PREDICATE_FACTORY; @@ -51,7 +53,7 @@ public class ViewBuilder { * @param source the source to set * @return the current builder instance */ - public ViewBuilder setWrapper(AbstractViewWrapper<String, ?> source) { + public ViewBuilder setWrapper(AbstractDataSource<String, ?> source) { this.source = source; return this; } @@ -64,7 +66,7 @@ public class ViewBuilder { * @return the current builder instance */ public ViewBuilder useHSQLDBSource(String url, String database) throws SQLException { - this.source = new SQLWrapper(new HSQLDBDriver(url, database)); + this.source = new SQLDataSource(new HSQLDBDriver(url, database)); return this; } @@ -78,7 +80,7 @@ public class ViewBuilder { * @return the current builder instance */ public ViewBuilder useMySQLSource(String url, String database, String user, String password) throws SQLException { - this.source = new SQLWrapper(new MySQLDriver(url, database, user, password)); + this.source = new SQLDataSource(new MySQLDriver(url, database, user, password)); return this; } @@ -92,7 +94,7 @@ public class ViewBuilder { * @return the current builder instance */ public ViewBuilder usePostgreSQLSource(String url, String database, String user, String password) throws SQLException { - this.source = new SQLWrapper(new PostgreSQLDriver(url, database, user, password)); + this.source = new SQLDataSource(new PostgreSQLDriver(url, database, user, password)); return this; } @@ -103,7 +105,7 @@ public class ViewBuilder { * @return the current builder instance */ public ViewBuilder useSQLiteSource(String url) throws SQLException { - this.source = new SQLWrapper(new SQLiteDriver(url)); + this.source = new SQLDataSource(new SQLiteDriver(url)); return this; } @@ -139,7 +141,7 @@ public class ViewBuilder { * * @return the configured source */ - public AbstractViewWrapper<String, ?> build() { + public AbstractDataSource<String, ?> build() { if (this.source == null) { throw new IllegalStateException("Source must be set before building."); } @@ -220,8 +222,8 @@ public class ViewBuilder { * @return the wrappers * @throws ViewBuilderException if an exception occurs */ - public static Collection<AbstractViewWrapper<String, ?>> createFactBases(String filename) throws ViewBuilderException { - Collection<AbstractViewWrapper<String, ?>> views = new ArrayList<>(); + public static Collection<DataSource<String, ?>> loadDataSources(String filename) throws ViewBuilderException { + Collection<DataSource<String, ?>> views = new ArrayList<>(); try { ViewDocument document = ViewParser.parse(filename); @@ -231,42 +233,42 @@ public class ViewBuilder { throw new ViewBuilderException("Unknown datasource for type " + d.getType()); } - AbstractViewWrapper<String, ?> wrapper = switch (typeOpt.get()) { + AbstractDataSource<String, ?> wrapper = switch (typeOpt.get()) { case HSQLDB -> { String url = d.getParameters().get("url"); String database = d.getParameters().get("database"); - yield new SQLWrapper(new HSQLDBDriver(url, database)); + yield new SQLDataSource(new HSQLDBDriver(url, database)); } case SQLITE -> { String url = d.getParameters().get("url"); - yield new SQLWrapper(new SQLiteDriver(url)); + yield new SQLDataSource(new SQLiteDriver(url)); } case MYSQL -> { String url = d.getParameters().get("url"); String database = d.getParameters().get("database"); String user = d.getParameters().get("user"); String password = d.getParameters().get("password"); - yield new SQLWrapper(new MySQLDriver(url, database, user, password)); + yield new SQLDataSource(new MySQLDriver(url, database, user, password)); } case POSTGRESQL -> { String url = d.getParameters().get("url"); String database = d.getParameters().get("database"); String user = d.getParameters().get("user"); String password = d.getParameters().get("password"); - yield new SQLWrapper(new PostgreSQLDriver(url, database, user, password)); + yield new SQLDataSource(new PostgreSQLDriver(url, database, user, password)); } case SPARQLENDPOINT -> { String url = d.getParameters().get("url"); - yield new SPARQLWrapper(url); + yield new SPARQLDataSource(url); } case MONGODB -> { // TODO Get parameters - yield new MongoDBWrapper("lot of params", "", "", List.of("")); + yield new MongoDBDataSource("lot of params", "", "", List.of("")); } case WEBAPI -> { String user = d.getParameters().get("user"); String password = d.getParameters().get("password"); - yield new WebAPIWrapper(user, password); + yield new WebAPIDataSource(user, password); } }; @@ -310,10 +312,10 @@ public class ViewBuilder { * @return the wrappers * @throws ViewBuilderException if an exception occur */ - public static Collection<AbstractViewWrapper<String, ?>> createFactBases(Collection<String> filePaths) throws ViewBuilderException { - Collection<AbstractViewWrapper<String, ?>> views = new ArrayList<>(); + public static Collection<DataSource<String, ?>> loadDataSources(Collection<String> filePaths) throws ViewBuilderException { + Collection<DataSource<String, ?>> views = new ArrayList<>(); for (String filename : filePaths) { - views.addAll(ViewBuilder.createFactBases(filename)); + views.addAll(ViewBuilder.loadDataSources(filename)); } return views; } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/AbstractViewWrapper.java b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/AbstractDataSource.java similarity index 50% rename from integraal/integraal-views/src/main/java/fr/boreal/views/datasource/AbstractViewWrapper.java rename to integraal/integraal-views/src/main/java/fr/boreal/views/datasource/AbstractDataSource.java index a1dcea31e2b6b488e533d976a067f5de9147ccae..d88d9aa33857e5fe470fb3fcb917bf13fb8946a2 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/AbstractViewWrapper.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/AbstractDataSource.java @@ -1,10 +1,8 @@ package fr.boreal.views.datasource; -import com.mongodb.internal.operation.MapReduceToCollectionOperation; -import fr.boreal.model.data.readable.QueryableData; import fr.boreal.model.data.readable.exception.EvaluationException; -import fr.boreal.model.data.readable.query.BasicPattern; -import fr.boreal.model.data.readable.query.BasicPatternBuilder; +import fr.boreal.model.data.readable.query.AtomicPattern; +import fr.boreal.model.data.readable.query.AtomicPatternBuilder; import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.*; import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; @@ -13,32 +11,33 @@ import fr.boreal.model.logicalElements.impl.SubstitutionImpl; import fr.boreal.storage.external.evaluator.NativeQueryEvaluator; import fr.boreal.views.specializer.Specializer; import fr.boreal.views.transformer.Transformer; +import fr.boreal.views.view.View; +import fr.boreal.views.view.ViewImpl; +import fr.boreal.views.view.ViewParameters; import fr.lirmm.boreal.util.stream.filter.FilterIteratorWithoutException; import fr.lirmm.boreal.util.stream.filter.MatchFilter; import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** * This wrapper represents data-sources accessed using mappings. - * Theses are sources queried by user-given queries with read-only rights + * These sources are queried by user-given queries with read-only rights * <br/> * A data-source can define several relational views, which associate a Predicate (of the relational view) to a specification of this view * * @param <NativeQueryType> the type used to represent the native query * @param <NativeResultType> the type used to represent the results as the native format */ -public abstract class AbstractViewWrapper<NativeQueryType, NativeResultType> implements QueryableData { +public abstract class AbstractDataSource<NativeQueryType, NativeResultType> implements DataSource<NativeQueryType, NativeResultType> { private String name; private final Specializer<NativeQueryType> specializer; private final NativeQueryEvaluator<NativeQueryType, NativeResultType> evaluator; private final Transformer<NativeResultType> transformer; - private final Map<Predicate, ViewParameters<NativeQueryType>> viewByPredicate; + private final Map<Predicate, View<NativeQueryType>> viewByPredicate; /** * Create a new wrapper over a data-source with a relational view @@ -46,8 +45,8 @@ public abstract class AbstractViewWrapper<NativeQueryType, NativeResultType> imp * @param evaluator to evaluate the native query * @param transformer to transform the native result into atoms */ - public AbstractViewWrapper(Specializer<NativeQueryType> specializer, NativeQueryEvaluator<NativeQueryType, NativeResultType> evaluator, Transformer<NativeResultType> transformer) { - this(null, specializer,evaluator,transformer); + protected AbstractDataSource(Specializer<NativeQueryType> specializer, NativeQueryEvaluator<NativeQueryType, NativeResultType> evaluator, Transformer<NativeResultType> transformer) { + this(null, specializer, evaluator, transformer); } /** @@ -57,7 +56,7 @@ public abstract class AbstractViewWrapper<NativeQueryType, NativeResultType> imp * @param evaluator to evaluate the native query * @param transformer to transform the native result into atoms */ - public AbstractViewWrapper(String name, Specializer<NativeQueryType> specializer, NativeQueryEvaluator<NativeQueryType, NativeResultType> evaluator, Transformer<NativeResultType> transformer) { + protected AbstractDataSource(String name, Specializer<NativeQueryType> specializer, NativeQueryEvaluator<NativeQueryType, NativeResultType> evaluator, Transformer<NativeResultType> transformer) { this.name = name; this.specializer = specializer; this.evaluator = evaluator; @@ -72,22 +71,22 @@ public abstract class AbstractViewWrapper<NativeQueryType, NativeResultType> imp * @param viewParameters associated to this view predicate */ public void registerView(Predicate p, ViewParameters<NativeQueryType> viewParameters) { - this.viewByPredicate.put(p, viewParameters); + this.viewByPredicate.put(p, new ViewImpl<>(p, Map.of(), viewParameters)); } /** * @param p the predicate representing the relational view * @return the native query associated to the view predicate p */ - public ViewParameters<NativeQueryType> getViewParameters(Predicate p) { - return this.viewByPredicate.get(p); + private ViewParameters<NativeQueryType> getViewParameters(Predicate p) { + return this.viewByPredicate.get(p).getViewParameters(); } /** * @param p the predicate representing the relational view * @return the native query specializer associated to the view predicate p */ - public Specializer<NativeQueryType> getSpecializer(Predicate p) { + private Specializer<NativeQueryType> getSpecializer(Predicate p) { return this.specializer; } @@ -95,7 +94,7 @@ public abstract class AbstractViewWrapper<NativeQueryType, NativeResultType> imp * @param p the predicate representing the relational view * @return the native query evaluator associated to the view predicate p */ - public NativeQueryEvaluator<NativeQueryType, NativeResultType> getEvaluator(Predicate p) { + private NativeQueryEvaluator<NativeQueryType, NativeResultType> getEvaluator(Predicate p) { return this.evaluator; } @@ -103,73 +102,43 @@ public abstract class AbstractViewWrapper<NativeQueryType, NativeResultType> imp * @param p the predicate representing the relational view * @return the native result transformer associated to the view predicate p */ - public Transformer<NativeResultType> getTransformer(Predicate p) { + private Transformer<NativeResultType> getTransformer(Predicate p) { return this.transformer; } /** * @return the predicates corresponding to the relational views of the datasource */ + @Override public Collection<Predicate> getPredicates() { return this.viewByPredicate.keySet(); } @Override public Stream<List<Term>> evaluate(BasicQuery query) throws EvaluationException { - List<Term> terms = new ArrayList<>(query.getPredicate().arity()); - Substitution substitution = new SubstitutionImpl(); - for (int i = 0; i < query.getPredicate().arity(); i++) { - Variable v = SameObjectTermFactory.instance().createOrGetFreshVariable(); - terms.add(v); - if (query.getAssignedTerms().containsKey(i)) { - substitution.add(v, query.getAssignedTerms().get(i)); - } - } - - return StreamSupport.stream( - Spliterators.spliteratorUnknownSize( - this.match(new AtomImpl(query.getPredicate(), terms), substitution), - 0), - false) - .map(Atom::getTermSequence); - } - - @Override - public Optional<Long> estimateBound(BasicQuery query) { - return Optional.empty(); - } - - @Override - public BasicPattern getBasicPattern(Predicate predicate) { - return new BasicPatternBuilder() - .withPredicate(predicate) - .withIndexablePatternsFunction((basicPattern -> Set.of())) - .withCreateQueriesFunction(((basicPattern, terms, substitution) -> Stream.of(new BasicQuery( - basicPattern, - IntStream.range(0, predicate.arity()).boxed() - .filter(i -> terms.get(i).isGround() || substitution.keys().contains(terms.get(i))) - .map(i -> Map.entry(i, substitution.createImageOf(terms.get(i)))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) - )))) - .build(); - } - - public Iterator<Atom> match(Atom a, Substitution s) { - Predicate p = a.getPredicate(); + Predicate p = query.getPredicate(); ViewParameters<NativeQueryType> viewParameters = this.getViewParameters(p); - ViewParameters<NativeQueryType> specializedViewParameters = this.getSpecializer(p).specialize(viewParameters, a, s); + ViewParameters<NativeQueryType> specializedViewParameters = + this.getSpecializer(p).specialize(viewParameters, query); Optional<NativeResultType> nativeResult = this.getEvaluator(p).evaluate(specializedViewParameters.nativeQuery()); if(nativeResult.isEmpty()) { - return Collections.emptyIterator(); + return Stream.empty(); } else { - Iterator<Atom> matched_atoms = this.getTransformer(p).transform(nativeResult.get(), specializedViewParameters, a, s); - return new FilterIteratorWithoutException<>(matched_atoms, new MatchFilter(a, s)); + return this.getTransformer(p).transform(nativeResult.get(), specializedViewParameters, query); } + } + @Override + public Optional<Long> estimateBound(BasicQuery query) { + return Optional.empty(); } + @Override + public AtomicPattern getBasicPattern(Predicate predicate) { + return this.viewByPredicate.get(predicate); + } /** * @return an optional that contains the datasource name if there is one @@ -182,35 +151,6 @@ public abstract class AbstractViewWrapper<NativeQueryType, NativeResultType> imp * @param name the new datasource name */ public void setName(String name) { - this.name=name; - } - - - - ///////////////////////////////////////////////// - // FactStorage methods - ///////////////////////////////////////////////// - - /*@Override - public Iterator<Atom> match(Atom a, Substitution s) { - Predicate p = a.getPredicate(); - ViewParameters<NativeQueryType> viewParameters = this.getViewParameters(p); - - ViewParameters<NativeQueryType> specializedViewParameters = this.getSpecializer(p).specialize(viewParameters, a, s); - - Optional<NativeResultType> nativeResult = this.getEvaluator(p).evaluate(specializedViewParameters.nativeQuery()); - if(nativeResult.isEmpty()) { - return Collections.emptyIterator(); - } else { - Iterator<Atom> matched_atoms = this.getTransformer(p).transform(nativeResult.get(), specializedViewParameters, a, s); - return new FilterIteratorWithoutException<>(matched_atoms, new MatchFilter(a, s)); - } - + this.name = name; } - - @Override - public Iterator<Atom> match(Atom a) { - return this.match(a, new SubstitutionImpl()); - }*/ - } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/DataSource.java b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/DataSource.java new file mode 100644 index 0000000000000000000000000000000000000000..d4e7b9be293949961150feec966077f6a7cda997 --- /dev/null +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/DataSource.java @@ -0,0 +1,10 @@ +package fr.boreal.views.datasource; + +import fr.boreal.model.data.readable.QueryableData; + +import java.util.Optional; + +public interface DataSource<NativeQueryType, NativeResultType> + extends QueryableData { + Optional<String> getName(); +} diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/MongoDBWrapper.java b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/MongoDBDataSource.java similarity index 80% rename from integraal/integraal-views/src/main/java/fr/boreal/views/datasource/MongoDBWrapper.java rename to integraal/integraal-views/src/main/java/fr/boreal/views/datasource/MongoDBDataSource.java index dfeb11e2bb421ceff1a48c8888bd9f930753f778..21e3795dc59feab6d255e8344f697b35a1f19bc5 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/MongoDBWrapper.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/MongoDBDataSource.java @@ -16,7 +16,7 @@ import fr.boreal.views.transformer.MongoDocumentTransformer; * @author Florent Tornil * */ -public class MongoDBWrapper extends AbstractViewWrapper<String, MongoCursor<Document>> { +public class MongoDBDataSource extends AbstractDataSource<String, MongoCursor<Document>> { /** * Create a new datasource over a mongodb server @@ -25,7 +25,7 @@ public class MongoDBWrapper extends AbstractViewWrapper<String, MongoCursor<Docu * @param collection the mongodb collection * @param projectionPaths the paths to project results */ - public MongoDBWrapper(String url, String database, String collection, List<String> projectionPaths) { + public MongoDBDataSource(String url, String database, String collection, List<String> projectionPaths) { super(new MandatoryParameterStringReplacement(), new MongoDBQueryEvaluator(url, database, collection), new MongoDocumentTransformer(projectionPaths)); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SPARQLWrapper.java b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SPARQLDataSource.java similarity index 84% rename from integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SPARQLWrapper.java rename to integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SPARQLDataSource.java index edf6f0f8dbb81844aec49a9f7f38417f3db3e8c3..5d77d3ace95baac53ce1dccefee68ce963597e4c 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SPARQLWrapper.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SPARQLDataSource.java @@ -13,13 +13,13 @@ import fr.boreal.views.transformer.SparqlTuplesTransformer; * @author Florent Tornil * */ -public class SPARQLWrapper extends AbstractViewWrapper<String, TupleQueryResult> { +public class SPARQLDataSource extends AbstractDataSource<String, TupleQueryResult> { /** * Create a new datasource on the endpoint * @param endpointUrl the url of the SPARQL endpoint */ - public SPARQLWrapper(String endpointUrl) { + public SPARQLDataSource(String endpointUrl) { super(new MandatoryParameterStringReplacement(), new SparqlQueryEvaluator(new SPARQLRepository(endpointUrl)), new SparqlTuplesTransformer()); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SQLWrapper.java b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SQLDataSource.java similarity index 82% rename from integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SQLWrapper.java rename to integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SQLDataSource.java index 7dcee8cfbc35280af15ed123ddca2fecfd39e55f..8ef3f209798fab185bf0c44c9922829274e914e3 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SQLWrapper.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/SQLDataSource.java @@ -14,14 +14,14 @@ import fr.boreal.views.transformer.SQLTuplesTransformer; * @author Florent Tornil * */ -public class SQLWrapper extends AbstractViewWrapper<String, List<Object[]>> { +public class SQLDataSource extends AbstractDataSource<String, List<Object[]>> { /** * Create a new datasource on a RDBMS * @param driver the SQL driver * @throws SQLException if an error occur */ - public SQLWrapper(RDBMSDriver driver) throws SQLException { + public SQLDataSource(RDBMSDriver driver) throws SQLException { super(new MandatoryParameterStringReplacement(), new SQLQueryEvaluator(driver), new SQLTuplesTransformer()); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/WebAPIWrapper.java b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/WebAPIDataSource.java similarity index 81% rename from integraal/integraal-views/src/main/java/fr/boreal/views/datasource/WebAPIWrapper.java rename to integraal/integraal-views/src/main/java/fr/boreal/views/datasource/WebAPIDataSource.java index 15ccf4d36e297aa34491bc007526f96c947b5a15..17723aa030238c94bfa027f71cbcc26e0ef777e6 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/WebAPIWrapper.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/WebAPIDataSource.java @@ -10,14 +10,14 @@ import fr.boreal.views.transformer.JSONStringTransformer; * @author Florent Tornil * */ -public class WebAPIWrapper extends AbstractViewWrapper<String, String> { +public class WebAPIDataSource extends AbstractDataSource<String, String> { /** * Create a new datasource on a web api * @param username the user login name * @param password the user login password */ - public WebAPIWrapper(String username, String password) { + public WebAPIDataSource(String username, String password) { super( new MandatoryParameterStringReplacement(), new HttpQueryEvaluator(username, password), new JSONStringTransformer()); diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/MandatoryParameterStringReplacement.java b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/MandatoryParameterStringReplacement.java index ccfcd473075cbed9551f37a15fd5fce5c0bb10c2..c61f178d409227a3159e857248d50d3b543b3c54 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/MandatoryParameterStringReplacement.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/MandatoryParameterStringReplacement.java @@ -4,10 +4,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Substitution; -import fr.boreal.views.datasource.ViewParameterSignature; -import fr.boreal.views.datasource.ViewParameters; +import fr.boreal.views.view.ViewParameterSignature; +import fr.boreal.views.view.ViewParameters; /** * This specializer replaces all occurrences of specifics substrings from the initial String query @@ -20,19 +21,19 @@ import fr.boreal.views.datasource.ViewParameters; public class MandatoryParameterStringReplacement implements Specializer<String> { @Override - public ViewParameters<String> specialize(ViewParameters<String> parameters, Atom a, Substitution s) { + public ViewParameters<String> specialize(ViewParameters<String> parameters, BasicQuery basicQuery) { String specializedQuery = parameters.nativeQuery(); Optional<String> specializedPosition = parameters.position(); List<ViewParameterSignature> specializedViewElements = new ArrayList<>(); List<ViewParameterSignature> viewElements = parameters.viewElements(); - for(int i = 0; i < a.getPredicate().arity(); ++i) { + for(int i = 0; i < basicQuery.getPredicate().arity(); ++i) { ViewParameterSignature element = viewElements.get(i); Optional<String> specializedSelection = element.selection(); if(element.isMandatory()) { - if(s.createImageOf(a.getTerm(i)).isFrozen(s)) { + if(basicQuery.getAssignedTerms().containsKey(i)) { String pattern = element.mandatoryAs().orElseThrow(); - String value = s.createImageOf(a.getTerm(i)).label(); + String value = basicQuery.getTerm(i).orElseThrow().label(); specializedQuery = specializedQuery.replaceAll(pattern, value); if(specializedPosition.isPresent()) { @@ -42,7 +43,7 @@ public class MandatoryParameterStringReplacement implements Specializer<String> specializedSelection = Optional.of(specializedSelection.get().replaceAll(pattern, value)); } } else { - throw new IllegalArgumentException("The view " + a.getPredicate() + " was called without a mandatory value for the parameter " + throw new IllegalArgumentException("The view " + basicQuery.getPredicate() + " was called without a mandatory value for the parameter " + element.mandatoryAs().orElseThrow()); } } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/NoSpecializer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/NoSpecializer.java index 32f982b985047a4684537e61efa5917ed3a1c4ad..9e417a44e9b41ad556ca265f4c336af9b0ce668f 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/NoSpecializer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/NoSpecializer.java @@ -1,8 +1,9 @@ package fr.boreal.views.specializer; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Substitution; -import fr.boreal.views.datasource.ViewParameters; +import fr.boreal.views.view.ViewParameters; /** * This specializer do nothing. @@ -14,7 +15,7 @@ import fr.boreal.views.datasource.ViewParameters; public class NoSpecializer<NativeQueryType> implements Specializer<NativeQueryType> { @Override - public ViewParameters<NativeQueryType> specialize(ViewParameters<NativeQueryType> parameters, Atom filter, Substitution s) { + public ViewParameters<NativeQueryType> specialize(ViewParameters<NativeQueryType> parameters, BasicQuery basicQuery) { return parameters; } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/OrderedStringReplacementSpecializer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/OrderedStringReplacementSpecializer.java index 15539f0d6952fd5e17b1d6ab319c69a3522cbade..8679978f395e7c562fb5c2be6ab05ce547e90b22 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/OrderedStringReplacementSpecializer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/OrderedStringReplacementSpecializer.java @@ -1,9 +1,12 @@ package fr.boreal.views.specializer; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; -import fr.boreal.views.datasource.ViewParameters; +import fr.boreal.views.view.ViewParameters; + +import java.util.Optional; /** * This specializer replaces a given placeholder from the initial String query by the frozen positions of the given atom. @@ -33,13 +36,13 @@ public class OrderedStringReplacementSpecializer implements Specializer<String> ///////////////////////////////////////////////// @Override - public ViewParameters<String> specialize(ViewParameters<String> parameters, Atom a, Substitution s) { + public ViewParameters<String> specialize(ViewParameters<String> parameters, BasicQuery basicQuery) { String query = parameters.nativeQuery(); int i = 0; - while(i < a.getPredicate().arity() && query.contains(this.placeholder)) { - Term t_a = a.getTerm(i); - if(t_a.isFrozen(s)) { - String replacement = s.createImageOf(t_a).label(); + while(i < basicQuery.getPredicate().arity() && query.contains(this.placeholder)) { + Optional<Term> t_a = basicQuery.getTerm(i); + if(t_a.isPresent()) { + String replacement = t_a.get().label(); query = query.replaceFirst(this.placeholder, replacement); ++i; } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/Specializer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/Specializer.java index 3fdac708c86327ea3b6b0e97f5afd7248c479569..ef360d6ac5c0e37c1f8c7de82fef1ae9add2fdfb 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/Specializer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/specializer/Specializer.java @@ -1,8 +1,9 @@ package fr.boreal.views.specializer; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Substitution; -import fr.boreal.views.datasource.ViewParameters; +import fr.boreal.views.view.ViewParameters; /** * Specialize the native query in order to take into account the given parameters. @@ -19,5 +20,5 @@ public interface Specializer<NativeQueryType> { * @param s substitution that specializes the given atom * @return the specialized view parameters */ - ViewParameters<NativeQueryType> specialize(ViewParameters<NativeQueryType> parameters, Atom a, Substitution s); + ViewParameters<NativeQueryType> specialize(ViewParameters<NativeQueryType> parameters, BasicQuery basicQuery); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/AbstractTransformer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/AbstractTransformer.java index 4dc052ac14d7ba9b87a2f6c2174c195920d3758f..ca01941895cfafb2590cd7f8b7f436c260493230 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/AbstractTransformer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/AbstractTransformer.java @@ -1,20 +1,18 @@ package fr.boreal.views.transformer; -import fr.boreal.model.logicalElements.api.Atom; -import fr.boreal.model.logicalElements.api.Substitution; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Term; -import fr.boreal.model.logicalElements.impl.AtomImpl; -import fr.boreal.views.datasource.ViewParameterSignature; -import fr.boreal.views.datasource.ViewParameters; +import fr.boreal.views.view.ViewParameterSignature; +import fr.boreal.views.view.ViewParameters; import fr.boreal.views.transformer.missingValue.FreezeHandler; import fr.boreal.views.transformer.missingValue.IgnoreHandler; import fr.boreal.views.transformer.missingValue.MissingValueHandler; import fr.boreal.views.transformer.missingValue.OptionalHandler; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Optional; +import java.util.stream.Stream; /** * @author Florent Tornil @@ -24,10 +22,10 @@ import java.util.Optional; public abstract class AbstractTransformer<NativeResultType> implements Transformer<NativeResultType> { @Override - public Iterator<Atom> transform(NativeResultType nativeResults, - ViewParameters<?> parameters, - Atom a, Substitution s) { - return this.transform(nativeResults, parameters.viewElements(), a, s); + public Stream<List<Term>> transform(NativeResultType nativeResults, + ViewParameters<?> parameters, + BasicQuery basicQuery) { + return this.transform(nativeResults, parameters.viewElements(), basicQuery); } /** @@ -35,34 +33,31 @@ public abstract class AbstractTransformer<NativeResultType> implements Transform * Some implementations may compute a filter using the given atom when converting the results * @param nativeResults the native results representing atoms * @param viewElements the signature of the view's tuples - * @param a the atom used for filtering / instantiation - * @param s the pre-affectation from variables of <code>a</code> to terms - * @return all the atoms represented by the native results + * @param basicQuery the query to answer + * @return all the term sequences represented by the native results */ - public abstract Iterator<Atom> transform(NativeResultType nativeResults, List<ViewParameterSignature> viewElements, Atom a, - Substitution s); + protected abstract Stream<List<Term>> transform(NativeResultType nativeResults, List<ViewParameterSignature> viewElements, BasicQuery basicQuery); /** * Convert a native object into the corresponding atom * @param nativeResult the native object * @param signatures the signature of the view's tuples - * @param a atom used for filtering - * @param s pre affectation - * @return the Term corresponding to the given object with respect to the signature + * @param basicQuery the query to answer + * @return the term sequence represented by the native results */ - public Optional<Atom> transformAtom(Object nativeResult, List<ViewParameterSignature> signatures, Atom a, Substitution s) { - int arity = a.getPredicate().arity(); + protected Optional<List<Term>> transformNativeResult(Object nativeResult, List<ViewParameterSignature> signatures, BasicQuery basicQuery) { + int arity = basicQuery.getPredicate().arity(); List<Term> terms = new ArrayList<>(arity); int nativeResultIndex = 0; for(int signatureIndex = 0; signatureIndex < signatures.size(); ++signatureIndex) { ViewParameterSignature signature = signatures.get(signatureIndex); if(signature.isMandatory()) { - Term givenValue = s.createImageOf(a.getTerm(signatureIndex)); + Term givenValue = basicQuery.getTerm(signatureIndex).orElseThrow(); terms.add(givenValue); } else { Object o = this.getObjectAtIndex(nativeResult, nativeResultIndex, signature); - Optional<Term> opt_t = this.transformTerm(o, signature, a, s); + Optional<Term> opt_t = this.transformTerm(o, signature); if(opt_t.isEmpty()) { return Optional.empty(); } else { @@ -71,10 +66,10 @@ public abstract class AbstractTransformer<NativeResultType> implements Transform } } } - return Optional.of(new AtomImpl(a.getPredicate(), terms)); + return Optional.of(terms); } - private Optional<Term> transformTerm(Object o, ViewParameterSignature signature, Atom a, Substitution s) { + private Optional<Term> transformTerm(Object o, ViewParameterSignature signature) { if(this.isMissingValue(o)) { MissingValueHandler missingHandler = switch (signature.missingValueHandling()) { case "IGNORE" -> new IgnoreHandler(); @@ -84,7 +79,7 @@ public abstract class AbstractTransformer<NativeResultType> implements Transform }; return missingHandler.handle(); } else { - return this.convertType(o, signature, a, s); + return this.convertType(o, signature); } } @@ -95,23 +90,21 @@ public abstract class AbstractTransformer<NativeResultType> implements Transform * @param signature signature of the element of the tuple to get * @return the native object at the given position of the native result */ - public abstract Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature); + protected abstract Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature); /** * Does the given object represents the native datasource missing (NULL) value * @param o a native element * @return true iff o represents the native type missing value */ - public abstract boolean isMissingValue(Object o); + protected abstract boolean isMissingValue(Object o); /** * Convert a native object into the corresponding term * @param o the native object * @param signature the signature of the view's tuple for the position of o - * @param a atom used for filtering - * @param s pre affectation * @return the Term corresponding to the given object with respect to the signature */ - public abstract Optional<Term> convertType(Object o, ViewParameterSignature signature, Atom a, Substitution s); + protected abstract Optional<Term> convertType(Object o, ViewParameterSignature signature); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/JSONStringTransformer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/JSONStringTransformer.java index 50849bc4f41b74666642fa1b3dcff5ef88851a69..79863a8d1a18a986dde860454be8d96a93cac30b 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/JSONStringTransformer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/JSONStringTransformer.java @@ -2,15 +2,15 @@ package fr.boreal.views.transformer; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPath; -import fr.boreal.model.logicalElements.api.Atom; -import fr.boreal.model.logicalElements.api.Substitution; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Term; import fr.boreal.model.logicalElements.factory.api.TermFactory; import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; -import fr.boreal.views.datasource.ViewParameterSignature; -import fr.boreal.views.datasource.ViewParameters; +import fr.boreal.views.view.ViewParameterSignature; +import fr.boreal.views.view.ViewParameters; import java.util.*; +import java.util.stream.Stream; /** * Transform a String representing a JSON object into atoms. @@ -42,38 +42,37 @@ public class JSONStringTransformer extends AbstractTransformer<String> { ///////////////////////////////////////////////// @Override - public Iterator<Atom> transform(String nativeResults, ViewParameters<?> parameters, Atom a, Substitution s) { - - Collection<Atom> atoms = new ArrayList<>(); + public Stream<List<Term>> transform(String nativeResults, ViewParameters<?> parameters, BasicQuery basicQuery) { Object document = Configuration.defaultConfiguration().jsonProvider().parse(nativeResults); List<Object> jsonEntries = JsonPath.read(document, parameters.position().orElseThrow()); List<ViewParameterSignature> signatures = parameters.viewElements(); - for(Object jsonEntry : jsonEntries) { - Optional<Atom> opt_viewAtom = this.transformAtom(jsonEntry, signatures, a, s); - opt_viewAtom.ifPresent(atoms::add); - } - return atoms.iterator(); + + return jsonEntries.stream() + .map(jsonEntry -> this.transformNativeResult(jsonEntry, signatures, basicQuery).orElse(null)) + .filter(Objects::nonNull); } @Override - public Iterator<Atom> transform(String nativeResults, List<ViewParameterSignature> viewElements, Atom a, - Substitution s) { + protected Stream<List<Term>> transform( + String nativeResults, + List<ViewParameterSignature> viewElements, + BasicQuery basicQuery) { throw new UnsupportedOperationException("[JSON Transformer] This transform method should not be called," + " please use the one with the whole parameters object"); } @Override - public boolean isMissingValue(Object o) { + protected boolean isMissingValue(Object o) { return o == null; } @Override - public Optional<Term> convertType(Object o, ViewParameterSignature signature, Atom a, Substitution s) { + protected Optional<Term> convertType(Object o, ViewParameterSignature signature) { return Optional.of(this.tf.createOrGetLiteral(o)); } @Override - public Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { + protected Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { return JsonPath.read(nativeResult, signature.selection().orElseThrow()); } } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/MongoDocumentTransformer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/MongoDocumentTransformer.java index 7077645c25bd163cef22afd7c7c82fc9c7ac01f7..486f623a119f54fd1e303996f3a8fcdad7bdf788 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/MongoDocumentTransformer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/MongoDocumentTransformer.java @@ -1,11 +1,11 @@ package fr.boreal.views.transformer; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import fr.boreal.model.data.readable.query.BasicQuery; import org.bson.Document; import com.mongodb.client.MongoCursor; @@ -18,7 +18,7 @@ import fr.boreal.model.logicalElements.factory.api.TermFactory; import fr.boreal.model.logicalElements.factory.impl.SameObjectPredicateFactory; import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; import fr.boreal.model.logicalElements.impl.AtomImpl; -import fr.boreal.views.datasource.ViewParameterSignature; +import fr.boreal.views.view.ViewParameterSignature; /** * Ignores results with no values for an asked path @@ -28,7 +28,7 @@ public class MongoDocumentTransformer extends AbstractTransformer<MongoCursor<Do private final TermFactory tf; - final List<String> projection_paths; + final List<String> projectionPaths; /** @@ -41,120 +41,129 @@ public class MongoDocumentTransformer extends AbstractTransformer<MongoCursor<Do /** * Create a new transformer for mongodb documents - * @param projection_paths the paths to project data + * @param projectionPaths the paths to project data * @param pf the predicate factory * @param tf the term factory */ - public MongoDocumentTransformer(List<String> projection_paths, PredicateFactory pf, TermFactory tf) { - this.projection_paths = projection_paths; + public MongoDocumentTransformer(List<String> projectionPaths, PredicateFactory pf, TermFactory tf) { + this.projectionPaths = projectionPaths; this.tf = tf; } @Override - public Iterator<Atom> transform(MongoCursor<Document> nativeResults, List<ViewParameterSignature> signatures, Atom a, Substitution s) { - return new DocumentToAtomIterator(nativeResults, a); + protected Stream<List<Term>> transform( + MongoCursor<Document> nativeResults, + List<ViewParameterSignature> signatures, + BasicQuery basicQuery) { + return StreamSupport.stream(new DocumentToAtomSplitIterator(nativeResults, basicQuery), false); } - class DocumentToAtomIterator implements Iterator<Atom> { - - final MongoCursor<Document> it; - final Atom filter_atom; + class DocumentToAtomSplitIterator implements Spliterator<List<Term>> { - Atom next_element = null; + private final MongoCursor<Document> it; + private final BasicQuery basicQuery; - DocumentToAtomIterator(MongoCursor<Document> nativeResults, Atom a) { + DocumentToAtomSplitIterator(MongoCursor<Document> nativeResults, BasicQuery basicQuery) { this.it = nativeResults; - this.filter_atom = a; + this.basicQuery = basicQuery; } @Override - public boolean hasNext() { - if(next_element != null) { + public boolean tryAdvance(Consumer<? super List<Term>> action) { + while (it.hasNext()) { + Document d = it.next(); + List<Term> terms = extractTerms(d); + + if (terms == null || !matchesFilter(terms)) { + continue; + } + + action.accept(terms); return true; - } else if(! this.it.hasNext()) { - return false; - } else { - this.computeNext(); - return next_element != null; } + return false; } @Override - public Atom next() { - if(hasNext()) { - Atom tmp = this.next_element; - this.next_element = null; - return tmp; - } - throw new NoSuchElementException(); + public Spliterator<List<Term>> trySplit() { + return null; // Splitting is not implemented in this version + } + @Override + public long estimateSize() { + return Long.MAX_VALUE; // Unknown size } - public void computeNext() { + @Override + public int characteristics() { + return ORDERED | NONNULL; + } - List<Term> terms = new ArrayList<>(); + private List<Term> extractTerms(Document document) { + List<Term> terms = new ArrayList<>(basicQuery.getPredicate().arity()); - if(!this.it.hasNext()) { - return; - } - Document d = this.it.next(); - - int diff = filter_atom.getPredicate().arity() - projection_paths.size(); - for(int i = 0; i < diff; i++) { - terms.add(filter_atom.getTerm(i)); + for (int i = 0; i < basicQuery.getPredicate().arity(); i++) { + if (basicQuery.getTerm(i).isPresent()) { + terms.add(basicQuery.getTerm(i).get()); + } else { + terms.add(null); + } } - // create terms - for(String path : projection_paths) { - String[] keys = path.split("\\."); - for(int i = 0; i < keys.length -1; i++) { + + int index = 0; + for (String path : projectionPaths) { + Document currentDoc = document; + String[] keys = path.split("\\."); + + for (int i = 0; i < keys.length - 1; i++) { String key = keys[i]; - if(d.containsKey(key) && d.get(key) instanceof Document) { - d = d.get(key, Document.class); + if (currentDoc.containsKey(key) && currentDoc.get(key) instanceof Document) { + currentDoc = currentDoc.get(key, Document.class); } else { - this.computeNext(); + return null; } } - String key = keys[keys.length-1]; - if (d.get(key) != null) { - String value = d.get(key).toString(); - Term t = tf.createOrGetLiteral(value); - terms.add(t); + + String key = keys[keys.length - 1]; + if (currentDoc.get(key) != null) { + String value = currentDoc.get(key).toString(); + while(terms.get(index) != null) ++index; + terms.set(index, tf.createOrGetLiteral(value)); } else { - this.computeNext(); + return null; } } + return terms; + } - // filter - for(int i = 0; i < filter_atom.getPredicate().arity(); i++) { - Term filter_term = filter_atom.getTerm(i); - Term result_term = terms.get(i); + private boolean matchesFilter(List<Term> terms) { + for (int i = 0; i < basicQuery.getPredicate().arity(); i++) { + Term filterTerm = basicQuery.getTerm(i).orElse(null); + Term resultTerm = terms.get(i); - if(!filter_term.isVariable() && !filter_term.equals(result_term)) { - this.computeNext(); + if (filterTerm != null && !filterTerm.equals(resultTerm)) { + return false; } } - - // create atom - this.next_element = new AtomImpl(this.filter_atom.getPredicate(), terms); + return true; } - } @Override - public Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { + protected Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { // TODO Auto-generated method stub return null; } @Override - public boolean isMissingValue(Object o) { + protected boolean isMissingValue(Object o) { // TODO Auto-generated method stub return false; } @Override - public Optional<Term> convertType(Object o, ViewParameterSignature signature, Atom a, Substitution s) { + protected Optional<Term> convertType(Object o, ViewParameterSignature signature) { // TODO Auto-generated method stub return Optional.empty(); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SQLTuplesTransformer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SQLTuplesTransformer.java index 8ff31da6f0a9fda04c028070a83fff42fcd64c06..dbc465329a2ad75394410101ff406c7d488bc834 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SQLTuplesTransformer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SQLTuplesTransformer.java @@ -1,17 +1,13 @@ package fr.boreal.views.transformer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Stream; -import fr.boreal.model.logicalElements.api.Atom; -import fr.boreal.model.logicalElements.api.Substitution; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Term; import fr.boreal.model.logicalElements.factory.api.TermFactory; import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; -import fr.boreal.views.datasource.ViewParameterSignature; +import fr.boreal.views.view.ViewParameterSignature; /** * Transform SQL tuples (java.net List<Object[]<) to Atoms @@ -47,27 +43,27 @@ public class SQLTuplesTransformer extends AbstractTransformer<List<Object[]>> { ///////////////////////////////////////////////// @Override - public Iterator<Atom> transform(List<Object[]> nativeResults, List<ViewParameterSignature> signatures, Atom a, Substitution s) { - Collection<Atom> atoms = new ArrayList<>(); - for(Object[] nativeResult : nativeResults) { - Optional<Atom> opt_viewAtom = this.transformAtom(nativeResult, signatures, a, s); - opt_viewAtom.ifPresent(atoms::add); - } - return atoms.iterator(); + protected Stream<List<Term>> transform( + List<Object[]> nativeResults, + List<ViewParameterSignature> signatures, + BasicQuery basicQuery) { + return nativeResults.stream() + .map(nativeResult -> this.transformNativeResult(nativeResult, signatures, basicQuery).orElse(null)) + .filter(Objects::nonNull); } @Override - public boolean isMissingValue(Object o) { + protected boolean isMissingValue(Object o) { return o == null; } @Override - public Optional<Term> convertType(Object o, ViewParameterSignature signature, Atom a, Substitution s) { + protected Optional<Term> convertType(Object o, ViewParameterSignature signature) { return Optional.of(this.tf.createOrGetLiteral(o)); } @Override - public Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { + protected Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { return ((Object[])nativeResult)[nativeResultIndex]; } } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SparqlTuplesTransformer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SparqlTuplesTransformer.java index d80d3a30b7829e46956daf1ebbeaf01c95566b81..dcb5733843df1f4015a92eb17966e84d0a60667c 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SparqlTuplesTransformer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/SparqlTuplesTransformer.java @@ -1,22 +1,18 @@ package fr.boreal.views.transformer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Stream; +import fr.boreal.model.data.readable.query.BasicQuery; import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.query.BindingSet; import org.eclipse.rdf4j.query.TupleQueryResult; -import fr.boreal.model.logicalElements.api.Atom; -import fr.boreal.model.logicalElements.api.Substitution; import fr.boreal.model.logicalElements.api.Term; import fr.boreal.model.logicalElements.factory.api.TermFactory; import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; -import fr.boreal.views.datasource.ViewParameterSignature; +import fr.boreal.views.view.ViewParameterSignature; /** * Transform Sparql tuples (rdf4j {@link TupleQueryResult}) to Atoms @@ -57,18 +53,19 @@ public class SparqlTuplesTransformer extends AbstractTransformer<TupleQueryResul ///////////////////////////////////////////////// @Override - public Iterator<Atom> transform(TupleQueryResult nativeResults, List<ViewParameterSignature> signatures, Atom a, Substitution s) { - Collection<Atom> atoms = new ArrayList<>(); + public Stream<List<Term>> transform( + TupleQueryResult nativeResults, + List<ViewParameterSignature> signatures, + BasicQuery basicQuery) { this.ordered_binding_names = nativeResults.getBindingNames(); - for(BindingSet nativeResult : nativeResults) { - Optional<Atom> opt_viewAtom = this.transformAtom(nativeResult, signatures, a, s); - opt_viewAtom.ifPresent(atoms::add); - } - return atoms.iterator(); + + return nativeResults.stream() + .map(nativeResult -> this.transformNativeResult(nativeResult, signatures, basicQuery).orElse(null)) + .filter(Objects::nonNull); } @Override - public boolean isMissingValue(Object o) { + protected boolean isMissingValue(Object o) { return !(o instanceof Value); } @@ -81,7 +78,7 @@ public class SparqlTuplesTransformer extends AbstractTransformer<TupleQueryResul // TODO: For now we only handle String and Integer values // TODO: Other values will be handled as String // We can also compute a first filter here according to constants of the atom - public Optional<Term> convertType(Object o, ViewParameterSignature signature, Atom a, Substitution s) { + protected Optional<Term> convertType(Object o, ViewParameterSignature signature) { if(o instanceof Value rdf4j_value) { if(rdf4j_value.isBNode()) { return Optional.of(this.tf.createOrGetVariable(rdf4j_value.stringValue())); @@ -104,7 +101,7 @@ public class SparqlTuplesTransformer extends AbstractTransformer<TupleQueryResul } @Override - public Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { + protected Object getObjectAtIndex(Object nativeResult, int nativeResultIndex, ViewParameterSignature signature) { return ((BindingSet)nativeResult).getBinding(this.ordered_binding_names.get(nativeResultIndex)).getValue(); } } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/Transformer.java b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/Transformer.java index ddab0615436c7aad2740d77f97ecab3cfbfce4a3..dece2866590ccbd97789fe7b8591a434d75d4269 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/Transformer.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/transformer/Transformer.java @@ -1,10 +1,14 @@ package fr.boreal.views.transformer; import java.util.Iterator; +import java.util.List; +import java.util.stream.Stream; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Atom; import fr.boreal.model.logicalElements.api.Substitution; -import fr.boreal.views.datasource.ViewParameters; +import fr.boreal.model.logicalElements.api.Term; +import fr.boreal.views.view.ViewParameters; /** * Transform a native result into Atoms @@ -18,10 +22,9 @@ public interface Transformer<NativeResultType> { * Some implementations may compute a filter using the given atom when converting the results * @param nativeResults the native results representing atoms * @param parameters the parameters of the view - * @param a the atom used for filtering / instantiation - * @param s the pre-affectation from variables of <code>a</code> to terms - * @return all the atoms represented by the native results + * @param basicQuery the query to answer + * @return all the term sequences represented by the native results */ - Iterator<Atom> transform(NativeResultType nativeResults, ViewParameters<?> parameters, Atom a, Substitution s); + Stream<List<Term>> transform(NativeResultType nativeResults, ViewParameters<?> parameters, BasicQuery basicQuery); } diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/view/View.java b/integraal/integraal-views/src/main/java/fr/boreal/views/view/View.java new file mode 100644 index 0000000000000000000000000000000000000000..cc263646d122ad0f3d5fd804605710f0d6e775f1 --- /dev/null +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/view/View.java @@ -0,0 +1,9 @@ +package fr.boreal.views.view; + +import fr.boreal.model.data.readable.query.AtomicPattern; +import fr.boreal.model.logicalElements.api.Predicate; +import fr.boreal.views.datasource.DataSource; + +public interface View<NativeQueryType> extends AtomicPattern { + ViewParameters<NativeQueryType> getViewParameters(); +} diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewImpl.java b/integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..6069e441f7a4de0856ba77d8edd68b15037c0721 --- /dev/null +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewImpl.java @@ -0,0 +1,63 @@ +package fr.boreal.views.view; + +import com.github.jsonldjava.shaded.com.google.common.collect.Sets; +import fr.boreal.model.data.readable.query.AbstractAtomicPattern; +import fr.boreal.model.data.readable.query.BasicQuery; +import fr.boreal.model.logicalElements.api.Predicate; +import fr.boreal.model.logicalElements.api.Substitution; +import fr.boreal.model.logicalElements.api.Term; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class ViewImpl<NativeQueryType> + extends AbstractAtomicPattern + implements View<NativeQueryType> { + private final ViewParameters<NativeQueryType> viewParameters; + + /** + * Constructs an AtomicPattern with specific constraints. + * + * @param predicate The predicate associated with this pattern. + * @param termConstraints A map associating positions (0-based index) with allowed term types. + */ + public ViewImpl( + Predicate predicate, + Map<Integer, Class<? extends Term>> termConstraints, + ViewParameters<NativeQueryType> viewParameters) { + super( + predicate, + IntStream.range(0, predicate.arity()).boxed() + .filter(i -> viewParameters.viewElements().get(i).isMandatory()) + .collect(Collectors.toSet()), + termConstraints); + this.viewParameters = viewParameters; + } + + @Override + public Set<Set<Integer>> getIndexablePatterns() { + return Set.of(this.getMandatoryPositions()); + } + + @Override + public Stream<BasicQuery> createQueries(Map<Integer, Term> positionsAssignation) { + if (this.hasAssignedMandatoryParameters(positionsAssignation)) { + return Stream.of(new BasicQuery( + this, + this.getMandatoryPositions().stream() + .map(i -> Map.entry(i, positionsAssignation.get(i))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) + )); + } + + return Stream.empty(); + } + @Override + public ViewParameters<NativeQueryType> getViewParameters() { + return viewParameters; + } +} diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/ViewParameterSignature.java b/integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewParameterSignature.java similarity index 94% rename from integraal/integraal-views/src/main/java/fr/boreal/views/datasource/ViewParameterSignature.java rename to integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewParameterSignature.java index 7f92fd413b6deaddb40f6f993925b571e7ebfc8a..11eb9c20090291aff1d8e22e4f1246a6d318cb6b 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/ViewParameterSignature.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewParameterSignature.java @@ -1,4 +1,4 @@ -package fr.boreal.views.datasource; +package fr.boreal.views.view; import java.util.Optional; diff --git a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/ViewParameters.java b/integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewParameters.java similarity index 93% rename from integraal/integraal-views/src/main/java/fr/boreal/views/datasource/ViewParameters.java rename to integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewParameters.java index 964a08efe342d32ffbc61b3636fe80bdecd07229..f0c928b31f7279f77b82e444218e8eb7d2e4e94f 100644 --- a/integraal/integraal-views/src/main/java/fr/boreal/views/datasource/ViewParameters.java +++ b/integraal/integraal-views/src/main/java/fr/boreal/views/view/ViewParameters.java @@ -1,4 +1,4 @@ -package fr.boreal.views.datasource; +package fr.boreal.views.view; import java.util.List; import java.util.Optional; diff --git a/integraal/integraal-views/src/main/java/module-info.java b/integraal/integraal-views/src/main/java/module-info.java index 954c8479d424c66061ef0889837b57b86a1004fe..aa17c8880a9d25f94f3caefba540ddc3adc323e9 100644 --- a/integraal/integraal-views/src/main/java/module-info.java +++ b/integraal/integraal-views/src/main/java/module-info.java @@ -19,6 +19,7 @@ module fr.boreal.views { requires rdf4j.repository.sparql; requires rdf4j.model.api; requires org.mongodb.driver.core; + requires jsonld.java; exports fr.boreal.views; exports fr.boreal.views.builder; diff --git a/integraal/integraal-views/src/test/java/fr/boreal/test/views/ViewTest.java b/integraal/integraal-views/src/test/java/fr/boreal/test/views/ViewTest.java index c20ab1dad9915a20a831866b56a96f819adbaf4a..daf66eaf9eb75c0fea5119b0b823310c690f333d 100644 --- a/integraal/integraal-views/src/test/java/fr/boreal/test/views/ViewTest.java +++ b/integraal/integraal-views/src/test/java/fr/boreal/test/views/ViewTest.java @@ -1,13 +1,12 @@ package fr.boreal.test.views; -import fr.boreal.model.logicalElements.api.Atom; +import fr.boreal.model.data.readable.exception.EvaluationException; +import fr.boreal.model.data.readable.query.BasicQuery; import fr.boreal.model.logicalElements.api.Predicate; -import fr.boreal.model.logicalElements.api.Variable; +import fr.boreal.model.logicalElements.api.Term; import fr.boreal.model.logicalElements.factory.impl.SameObjectPredicateFactory; -import fr.boreal.model.logicalElements.factory.impl.SameObjectTermFactory; -import fr.boreal.model.logicalElements.impl.AtomImpl; import fr.boreal.views.builder.ViewBuilder; -import fr.boreal.views.datasource.AbstractViewWrapper; +import fr.boreal.views.datasource.DataSource; import org.junit.Assert; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; @@ -17,7 +16,8 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Collection; -import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.stream.Stream; @RunWith(Parameterized.class) @@ -27,37 +27,27 @@ class ViewTest { public static final Predicate cityZip = SameObjectPredicateFactory.instance().createOrGetPredicate("cityZip", 2); public static final Predicate concept = SameObjectPredicateFactory.instance().createOrGetPredicate("concept", 1); - // Terms - public static final Variable x = SameObjectTermFactory.instance().createOrGetVariable("X"); - public static final Variable y = SameObjectTermFactory.instance().createOrGetVariable("Y"); - - // Atoms - public static final Atom cityZipQuery = new AtomImpl(cityZip, x, y); - public static final Atom conceptQuery = new AtomImpl(concept, x); - @Parameterized.Parameters static Stream<Arguments> data() { return Stream.of( - Arguments.of("./src/test/resources/wikidata_web_api.vd", cityZipQuery), - Arguments.of("./src/test/resources/dbpedia_sparql_endpoint.vd", conceptQuery) + Arguments.of("./src/test/resources/wikidata_web_api.vd", cityZip), + Arguments.of("./src/test/resources/dbpedia_sparql_endpoint.vd", concept) ); } - /*@DisplayName("Test querying views from a view declaration file") + @DisplayName("Test querying views from a view declaration file") @ParameterizedTest(name = "{index}: querying {1} on {0} should work ...") @MethodSource("data") - public void dlgpViewImport(String vdFilePath, Atom query) throws ViewBuilder.ViewBuilderException { - Collection<AbstractViewWrapper<String, ?>> wrappers = ViewBuilder.createFactBases(vdFilePath); - AbstractViewWrapper<String, ?> wrapper = wrappers.stream().findAny().orElseThrow(); - Iterator<Atom> results = wrapper.match(query); - int count = 0; - while (results.hasNext()) { - results.next(); - count++; - } - Assert.assertTrue(count>0); - }*/ + public void dlgpViewImport(String vdFilePath, Predicate predicate) throws ViewBuilder.ViewBuilderException, EvaluationException { + Collection<? extends DataSource<String, ?>> dataSources = ViewBuilder.loadDataSources(vdFilePath); + DataSource<String, ?> dataSource = dataSources.stream().findAny().orElseThrow(); + BasicQuery basicQuery = dataSource.getBasicPattern(predicate).createQueries(Map.of()).findAny().orElseThrow(); + List<List<Term>> results = dataSource.evaluate(basicQuery).toList(); + + results.stream().forEach(l -> Assert.assertEquals(l.size(), predicate.arity())); + Assert.assertFalse(results.isEmpty()); + } }