Package lupos.rif

Source Code of lupos.rif.BasicIndexRuleEvaluator

/**
* Copyright (c) 2013, Institute of Information Systems (Sven Groppe and contributors of LUPOSDATE), University of Luebeck
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*   - Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*     disclaimer.
*   - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*     following disclaimer in the documentation and/or other materials provided with the distribution.
*   - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*     products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lupos.rif;

import java.io.StringReader;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

import lupos.datastructures.bindings.Bindings;
import lupos.datastructures.bindings.BindingsMap;
import lupos.datastructures.items.Item;
import lupos.datastructures.items.Triple;
import lupos.datastructures.items.Variable;
import lupos.datastructures.items.literal.LiteralFactory;
import lupos.datastructures.items.literal.URILiteral;
import lupos.datastructures.queryresult.GraphResult;
import lupos.datastructures.queryresult.QueryResult;
import lupos.engine.evaluators.BasicIndexQueryEvaluator;
import lupos.engine.evaluators.CommonCoreQueryEvaluator;
import lupos.engine.evaluators.MemoryIndexQueryEvaluator;
import lupos.engine.evaluators.QueryEvaluator;
import lupos.engine.evaluators.RDF3XQueryEvaluator;
import lupos.engine.evaluators.StreamQueryEvaluator;
import lupos.engine.operators.BasicOperator;
import lupos.engine.operators.OperatorIDTuple;
import lupos.engine.operators.application.Application;
import lupos.engine.operators.application.CollectRIFResult;
import lupos.engine.operators.index.BasicIndexScan;
import lupos.engine.operators.index.Indices;
import lupos.engine.operators.index.Root;
import lupos.engine.operators.messages.BoundVariablesMessage;
import lupos.engine.operators.multiinput.join.Join;
import lupos.engine.operators.singleinput.Construct;
import lupos.engine.operators.singleinput.Result;
import lupos.engine.operators.singleinput.generate.Generate;
import lupos.engine.operators.singleinput.sparul.Insert;
import lupos.engine.operators.stream.Window;
import lupos.engine.operators.tripleoperator.TriplePattern;
import lupos.engine.operators.tripleoperator.patternmatcher.PatternMatcher;
import lupos.misc.ArgumentParser;
import lupos.misc.Tuple;
import lupos.misc.debug.BasicOperatorByteArray;
import lupos.misc.debug.DebugStep;
import lupos.optimizations.logical.rules.DebugContainer;
import lupos.optimizations.logical.rules.generated.RIFRules0RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules10RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules11RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules12RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules13RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules14RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules15RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules16RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules1RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules2RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules3RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules4RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules5RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules6RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules7RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules8RulePackage;
import lupos.optimizations.logical.rules.generated.RIFRules9RulePackage;
import lupos.optimizations.physical.PhysicalOptimizations;
import lupos.rdf.Prefix;
import lupos.rif.datatypes.Predicate;
import lupos.rif.datatypes.RuleResult;
import lupos.rif.generated.parser.RIFParser;
import lupos.rif.generated.syntaxtree.CompilationUnit;
import lupos.rif.model.Document;
import lupos.rif.operator.ConstructPredicate;
import lupos.rif.operator.InsertIndexScan;
import lupos.rif.visitor.BuildOperatorGraphRuleVisitor;
import lupos.rif.visitor.NormalizeRuleVisitor;
import lupos.rif.visitor.ParseSyntaxTreeVisitor;
import lupos.rif.visitor.ResolveListsRuleVisitor;
import lupos.rif.visitor.RuleDependencyGraphVisitor;
import lupos.rif.visitor.RuleFilteringVisitor;
import lupos.rif.visitor.SubstituteFunctionCallsVisitor;
import lupos.rif.visitor.ValidateRuleVisitor;
import lupos.sparql1_1.Node;
import lupos.sparql1_1.operatorgraph.helper.IndexScanCreatorInterface;

public class BasicIndexRuleEvaluator extends QueryEvaluator<Node> {
  protected final CommonCoreQueryEvaluator<Node> evaluator;
  private CompilationUnit compilationUnit;
  private Document rifDocument;

  /**
   * This constructor initializes the rule evaluator using the given query evaluator as underlying query evaluator
   * @param evaluator the underlying query evaluator
   * @throws Exception
   */
  public BasicIndexRuleEvaluator(final CommonCoreQueryEvaluator<Node> evaluator)
      throws Exception {
    super();
    this.evaluator = evaluator;
  }

  /**
   * this constructor setups a rule evaluator, which works in main memory
   * @throws Exception
   */
  public BasicIndexRuleEvaluator() throws Exception{
    this(false);
  }

  /**
   * this constructor setups a rule evaluator, which works in main memory
   * @param stream if stream is true the rule evaluator for streams is used, otherwise the main memory evaluator
   * @throws Exception
   */
  public BasicIndexRuleEvaluator(final boolean stream) throws Exception{
    super();
    this.evaluator = (stream)? new StreamQueryEvaluator(): new MemoryIndexQueryEvaluator();
    this.evaluator.setupArguments();
    this.evaluator.getArgs().set("debug", DEBUG.ALL);
    this.evaluator.getArgs().set("result", QueryResult.TYPE.MEMORY);
    this.evaluator.getArgs().set("codemap", LiteralFactory.MapType.HASHMAP);
    this.evaluator.getArgs().set("distinct", CommonCoreQueryEvaluator.DISTINCT.HASHSET);
    this.evaluator.getArgs().set("optional", CommonCoreQueryEvaluator.JOIN.HASHMAPINDEX);
    this.evaluator.getArgs().set("type", "Turtle");
    this.evaluator.getArgs().set("datastructure", Indices.DATA_STRUCT.HASHMAP);
    this.evaluator.init();
  }

  /**
   * this constructor setups a rule evaluator, which uses disk-based indices
   * (it uses a RDF3XQueryEvaluator as underlying query evaluator)
   * @param directoryOfIndices the directory, in which the indices have been constructed
   * @throws Exception
   */
  public BasicIndexRuleEvaluator(final String directoryOfIndices) throws Exception{
    super();
    final RDF3XQueryEvaluator rdf3xEvaluator = new RDF3XQueryEvaluator();
    rdf3xEvaluator.loadLargeScaleIndices(directoryOfIndices);
    this.evaluator = rdf3xEvaluator;
  }

  @Override
  public long compileQuery(final String query) throws Exception {
    return this.compileQuery(query, this.evaluator.createIndexScanCreator());
  }

  public long compileQuery(
      final String query, final IndexScanCreatorInterface indexScanCreator) throws Exception {
    final Date start = new Date();

    final RIFParser parser = new RIFParser(new StringReader(query));
    this.compilationUnit = parser.CompilationUnit();
    this.rifDocument = (Document) this.compilationUnit.accept(new ParseSyntaxTreeVisitor(), null);
    final BuildOperatorGraphRuleVisitor forward = new BuildOperatorGraphRuleVisitor(indexScanCreator);
    final ValidateRuleVisitor valVisitor = new ValidateRuleVisitor();
    final NormalizeRuleVisitor normVisitor = new NormalizeRuleVisitor();
    final SubstituteFunctionCallsVisitor subVisitor = new SubstituteFunctionCallsVisitor();
    final ResolveListsRuleVisitor listVisitor = new ResolveListsRuleVisitor();
    final RuleDependencyGraphVisitor dependencyVisitor = new RuleDependencyGraphVisitor();
    final RuleFilteringVisitor filteringVisitor = new RuleFilteringVisitor();

    this.rifDocument = (Document) this.rifDocument.accept(subVisitor, null);
    this.rifDocument = (Document) this.rifDocument.accept(listVisitor, null);
    this.rifDocument = (Document) this.rifDocument.accept(normVisitor, null);
    this.rifDocument.accept(valVisitor, null);
    this.rifDocument.accept(dependencyVisitor, null);
    this.rifDocument.accept(filteringVisitor, null);

    final Class<? extends Bindings> clazz = Bindings.instanceClass;
    Bindings.instanceClass = BindingsMap.class;
    final Result res = (Result) this.rifDocument.accept(forward, null);
    this.evaluator.setResult(res);
    Bindings.instanceClass = clazz;

    final BasicOperator root = indexScanCreator.getRoot();
    this.evaluator.setRootNode(root);

    root.setParents();
    root.detectCycles();
    root.sendMessage(new BoundVariablesMessage());
    this.evaluator.setBindingsVariablesBasedOnOperatorgraph();

    return new Date().getTime() - start.getTime();
  }

  @Override
  public long logicalOptimization() {
    final Date start = new Date();
    this.evaluator.logicalOptimization();
    this.evaluator.setBindingsVariablesBasedOnOperatorgraph();
    final RIFRules0RulePackage rules0 = new RIFRules0RulePackage();
    rules0.applyRules(this.evaluator.getRootNode());
    final RIFRules1RulePackage rules1 = new RIFRules1RulePackage();
    rules1.applyRules(this.evaluator.getRootNode());
    final RIFRules2RulePackage rules2 = new RIFRules2RulePackage();
    rules2.applyRules(this.evaluator.getRootNode());
    final RIFRules3RulePackage rules3 = new RIFRules3RulePackage();
    rules3.applyRules(this.evaluator.getRootNode());
    final RIFRules4RulePackage rules4 = new RIFRules4RulePackage();
    rules4.applyRules(this.evaluator.getRootNode());
    final RIFRules5RulePackage rules5 = new RIFRules5RulePackage();
    rules5.applyRules(this.evaluator.getRootNode());
    final RIFRules6RulePackage rules6 = new RIFRules6RulePackage();
    rules6.applyRules(this.evaluator.getRootNode());
    final RIFRules7RulePackage rules7 = new RIFRules7RulePackage();
    rules7.applyRules(this.evaluator.getRootNode());
    final RIFRules8RulePackage rules8 = new RIFRules8RulePackage();
    rules8.applyRules(this.evaluator.getRootNode());
    final RIFRules9RulePackage rules9 = new RIFRules9RulePackage();
    rules9.applyRules(this.evaluator.getRootNode());
    final RIFRules10RulePackage rules10 = new RIFRules10RulePackage();
    rules10.applyRules(this.evaluator.getRootNode());
    final RIFRules11RulePackage rules11 = new RIFRules11RulePackage();
    rules11.applyRules(this.evaluator.getRootNode());
    final RIFRules12RulePackage rules12 = new RIFRules12RulePackage();
    rules12.applyRules(this.evaluator.getRootNode());
    final RIFRules13RulePackage rules13 = new RIFRules13RulePackage();
    rules13.applyRules(this.evaluator.getRootNode());
    final RIFRules14RulePackage rules14 = new RIFRules14RulePackage();
    rules14.applyRules(this.evaluator.getRootNode());
    this.evaluator.getRootNode().sendMessage(new BoundVariablesMessage());
    this.evaluator.logicalOptimization();
    return new Date().getTime() - start.getTime();
  }

  @Override
  public List<DebugContainer<BasicOperatorByteArray>> logicalOptimizationDebugByteArray(
      final Prefix prefixInstance) {
    final List<DebugContainer<BasicOperatorByteArray>> result = new LinkedList<DebugContainer<BasicOperatorByteArray>>();
    result.add(new DebugContainer<BasicOperatorByteArray>(
        "Before logical optimization...",
        "logicaloptimizationPackageDescription", BasicOperatorByteArray
        .getBasicOperatorByteArray(this.evaluator.getRootNode().deepClone(),
            prefixInstance)));
    result.addAll(this.evaluator.logicalOptimizationDebugByteArray(prefixInstance));
    this.evaluator.setBindingsVariablesBasedOnOperatorgraph();
    final RIFRules0RulePackage rules0 = new RIFRules0RulePackage();
    result.addAll(rules0.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules1RulePackage rules1 = new RIFRules1RulePackage();
    result.addAll(rules1.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules2RulePackage rules2 = new RIFRules2RulePackage();
    result.addAll(rules2.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules3RulePackage rules3 = new RIFRules3RulePackage();
    result.addAll(rules3.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules4RulePackage rules4 = new RIFRules4RulePackage();
    result.addAll(rules4.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules5RulePackage rules5 = new RIFRules5RulePackage();
    result.addAll(rules5.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules6RulePackage rules6 = new RIFRules6RulePackage();
    result.addAll(rules6.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules7RulePackage rules7 = new RIFRules7RulePackage();
    result.addAll(rules7.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules8RulePackage rules8 = new RIFRules8RulePackage();
    result.addAll(rules8.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules9RulePackage rules9 = new RIFRules9RulePackage();
    result.addAll(rules9.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules10RulePackage rules10 = new RIFRules10RulePackage();
    result.addAll(rules10.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules11RulePackage rules11 = new RIFRules11RulePackage();
    result.addAll(rules11.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules12RulePackage rules12 = new RIFRules12RulePackage();
    result.addAll(rules12.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules13RulePackage rules13 = new RIFRules13RulePackage();
    result.addAll(rules13.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    final RIFRules14RulePackage rules14 = new RIFRules14RulePackage();
    result.addAll(rules14.applyRulesDebugByteArray(this.evaluator.getRootNode(), prefixInstance));
    this.evaluator.getRootNode().sendMessage(new BoundVariablesMessage());
    result.addAll(this.evaluator.logicalOptimizationDebugByteArray(prefixInstance));
    return result;
  }

  @Override
  public long physicalOptimization() {
    final long start = (new Date()).getTime();
    PhysicalOptimizations.addReplacement("multiinput.join.", "IndexJoinWithDuplicateElimination", "HashMapIndexJoinWithDuplicateElimination");
    this.evaluator.physicalOptimization();
    final RIFRules15RulePackage rules15 = new RIFRules15RulePackage();
    rules15.applyRules(this.evaluator.getRootNode());
    final RIFRules16RulePackage rules16 = new RIFRules16RulePackage();
    rules16.applyRules(this.evaluator.getRootNode());
    this.getRootNode().deleteParents();
    this.getRootNode().setParents();
    this.getRootNode().detectCycles();
//    this.getRootNode().sendMessage(new BoundVariablesMessage());
    return (new Date()).getTime() - start;
  }

  @Override
  public List<DebugContainer<BasicOperatorByteArray>> physicalOptimizationDebugByteArray(final Prefix prefixInstance) {
    this.physicalOptimization();
    final LinkedList<DebugContainer<BasicOperatorByteArray>> debugResult = new LinkedList<DebugContainer<BasicOperatorByteArray>>();
    debugResult.add(new DebugContainer<BasicOperatorByteArray>(
        "After physical optimization...", "physicaloptimizationRule",
        BasicOperatorByteArray.getBasicOperatorByteArray(
            this.getRootNode().deepClone(), prefixInstance)));
    return debugResult;
  }

  @Override
  public long evaluateQuery() throws Exception {
    return this.evaluator.evaluateQuery();
  }

  @Override
  public long evaluateQueryDebugSteps(final DebugStep debugstep, final Application application) throws Exception {
    return this.evaluator.evaluateQueryDebugSteps(debugstep, application);
  }

  public QueryResult getResultWithOnDemandInference(final String inferenceRuleset, final String query) throws Exception{
    return this.getResultWithOnDemandInference(inferenceRuleset, query, false);
  }

  public QueryResult getResultWithOnDemandInference(final String inferenceRuleset, final String query, final boolean oneTime) throws Exception{
    this.compileQueryAndInferenceIntoOneOperatorgraph(inferenceRuleset, query);
    this.logicalOptimization();
    this.physicalOptimization();
    return this.getResult(oneTime);
  }

  @Override
  public QueryResult getResult() throws Exception {
    return this.getResult(false);
  }

  public QueryResult getResult(final boolean oneTime) throws Exception {
    final CollectRIFResult cr = new CollectRIFResult(oneTime);
    this.evaluator.getResultOperator().addApplication(cr);
    this.evaluator.evaluateQuery();
    return cr.getResult();
  }

  public QueryResult[] getResults() throws Exception {
    return this.getResults(false);
  }

  public QueryResult[] getResults(final boolean oneTime) throws Exception {
    final CollectRIFResult cr = new CollectRIFResult(oneTime);
    this.evaluator.getResultOperator().addApplication(cr);
    this.evaluator.evaluateQuery();
    return cr.getQueryResults();
  }

  public CollectRIFResult getCollectedResults(final boolean oneTime) throws Exception {
    final CollectRIFResult cr = new CollectRIFResult(oneTime);
    this.evaluator.getResultOperator().addApplication(cr);
    this.evaluator.evaluateQuery();
    return cr;
  }

  public Result getResultOperator(){
    return this.evaluator.getResultOperator();
  }

  public BasicOperator getRootNode(){
    return this.evaluator.getRootNode();
  }

  @Override
  public ArgumentParser getArgs() {
    return this.evaluator.getArgs();
  }


  public CommonCoreQueryEvaluator<Node> getEvaluator() {
    return this.evaluator;
  }

  @Override
  public long prepareInputData(final Collection<URILiteral> defaultGraphs,
      final Collection<URILiteral> namedGraphs) throws Exception {
    return this.evaluator.prepareInputData(defaultGraphs, namedGraphs);
  }

  @Override
  public long prepareInputDataWithSourcesOfNamedGraphs(
      final Collection<URILiteral> defaultGraphs,
      final Collection<Tuple<URILiteral, URILiteral>> namedGraphs)
      throws Exception {
    return this.evaluator.prepareInputDataWithSourcesOfNamedGraphs(defaultGraphs, namedGraphs);
  }

  public CompilationUnit getCompilationUnit() {
    return this.compilationUnit;
  }

  public Document getDocument() {
    return this.rifDocument;
  }

  public Root getRoot() {
    return (Root) this.evaluator.getRootNode();
  }

  @Override
  public void setupArguments() {
    if(this.evaluator != null) {
      this.evaluator.setupArguments();
    }
  }

  @Override
  public void init() throws Exception {
    if(this.evaluator != null) {
      this.evaluator.init();
    }
  }

  @Override
  public void prepareForQueryDebugSteps(final DebugStep debugstep) {
    if(this.evaluator != null) {
      this.evaluator.prepareForQueryDebugSteps(debugstep);
    }
  }

  private final static URILiteral rif_error = LiteralFactory.createStringURILiteralWithoutException("<http://www.w3.org/2007/rif#error>");

  /**
   *
   * @return return a rule result with all predicates rif:error, which are detected errors in the ontology!
   * @throws Exception
   */
  public RuleResult inferTriplesAndStoreInDataset() throws Exception {
    final CollectRIFResult cr = this.getCollectedResults(true);
    final RuleResult result = new RuleResult();
    if(this.evaluator instanceof BasicIndexQueryEvaluator){
      for(final QueryResult qr: cr.getQueryResults()){
        if(qr instanceof GraphResult){
          final GraphResult gr = (GraphResult) qr;
          for(final Triple t: gr.getGraphResultTriples()){
            final Collection<Indices> ci = ((BasicIndexQueryEvaluator)this.evaluator).getDataset().getDefaultGraphIndices();
            for (final Indices indices : ci) {
              indices.add(t);
            }
          }
        } else if(qr instanceof RuleResult){
          final RuleResult rr = (RuleResult) qr;
          for(final Predicate predicate: rr.getPredicateResults()){
            if(rif_error.equals(predicate.getName())){
              result.getPredicateResults().add(predicate);
            }
          }
        }
      }
    } else if (this.evaluator instanceof StreamQueryEvaluator) {
      String s = "";
      for(final QueryResult qr: cr.getQueryResults()){
        if(qr instanceof GraphResult){
          final GraphResult gr = (GraphResult) qr;
          // TODO duplicated triple elimination!
          for(final Triple t: gr.getGraphResultTriples()){
            if(!t.getSubject().isBlank() && !t.getSubject().isURI()){
              System.out.println("Warning: The subject of the inferred triple "+t+" is neither an uri nor a blank node and thus the triple will be ignored!");
            } else if(!t.getPredicate().isURI()){
              System.out.println("Warning: The predicate of the inferred triple "+t+" is not an uri and thus the triple will be ignored!");
            } else {
              s += t.getSubject() + " " + t.getPredicate() + " " +t.getObject() + " .\n";
            }
          }
        } else if(qr instanceof RuleResult){
          final RuleResult rr = (RuleResult) qr;
          for(final Predicate predicate: rr.getPredicateResults()){
            if(rif_error.equals(predicate.getName())){
              result.getPredicateResults().add(predicate);
            }
          }
        }
      }
      final URILiteral in = LiteralFactory.createStringURILiteral("<inlinedata:"+s+">");
      ((StreamQueryEvaluator)this.evaluator).addToDefaultGraphs(in);
    } else {
      throw new Exception("Unkwon QueryEvaluator Type: " + this.evaluator.getClass());
    }
    if(result.getPredicateResults().size()==0){
      return null;
    } else {
      return result;
    }
  }

  public QueryResult materializeInferredTriplesOfRifEngineAndGetResultOfSPARQLQuery(final String query) throws Exception {
      this.inferTriplesAndStoreInDataset();
      return this.evaluator.getResult(query);
  }

  public long compileQueryAndInferenceIntoOneOperatorgraph(final String inferenceRuleset, final String query) throws Exception {
    final Date a = new Date();
    this.compileQuery(inferenceRuleset);
    final BasicOperator rootInference = this.getRootNode();
    final Result resultInference = this.getResultOperator();
    this.evaluator.compileQuery(query);
    integrateInferenceOperatorgraphIntoQueryOperatorgraph(rootInference, resultInference, this.evaluator.getRootNode(), this.evaluator.getResultOperator());
    this.evaluator.setBindingsVariablesBasedOnOperatorgraph();
    return ((new Date()).getTime() - a.getTime());
  }

  public static void integrateInferenceOperatorgraphIntoQueryOperatorgraph(final BasicOperator rootInference, final Result resultInference, final BasicOperator rootQuery, final Result resultQuery){
    // first determine those operations, which generate triples of the result (and delete the other ones (and their preceding operators...))
    // also replace Construct operators with Generate operators!
    final LinkedList<Generate> listOfConstructedTripel = new LinkedList<Generate>();
    for(final BasicOperator bo: new LinkedList<BasicOperator>(resultInference.getPrecedingOperators())){
      if(bo instanceof Construct){
        final Construct construct = (Construct)bo;
        // split construct and replace them with Generate operators!
        for(final TriplePattern tp: construct.getTemplates()){
          final Generate generate = new Generate(tp);
          for(final BasicOperator father: construct.getPrecedingOperators()){
            father.addSucceedingOperator(generate);
            generate.addPrecedingOperator(father);
          }
          listOfConstructedTripel.add(generate);
          // remove old construct
          for(final BasicOperator father: new HashSet<BasicOperator>(construct.getPrecedingOperators())){
            father.removeSucceedingOperator(construct);
            construct.removePrecedingOperator(father);
          }
        }
      } else if(bo instanceof ConstructPredicate){
        final ConstructPredicate cp = (ConstructPredicate) bo;
        boolean toDelete = true;
        for(final Tuple<URILiteral, List<Item>> tuple: cp.getPredicatePattern()){
          if(BasicIndexRuleEvaluator.rif_error.equals(tuple.getFirst())){
            // predicates as result of detecting errors in the ontology should remain!
            toDelete = false;
            break;
          }
        }
        if(toDelete){
          deletePrecedingOperators(bo);
        } else {
          cp.setSucceedingOperator(new OperatorIDTuple(resultQuery, 0));
          resultQuery.addPrecedingOperator(cp);
        }
      } else {
        deletePrecedingOperators(bo);
      }
    }
    // now connect generate operations with triple patterns/index scans of the query operator graph
    final LinkedList<BasicOperator> toBeConnectedTo = determine1stLevelTriplePatternOrIndexScans(rootQuery);
    for(final Generate generate: listOfConstructedTripel){
      generate.getSucceedingOperators().clear();
      final Item[] generateItems = generate.getValueOrVariable();
      for(final BasicOperator tpOrIndexScan: new LinkedList<BasicOperator>(toBeConnectedTo)){
        if(tpOrIndexScan instanceof TriplePattern){
          final TriplePattern tpi = (TriplePattern) tpOrIndexScan;
          if(BasicIndexRuleEvaluator.isMatching(tpi, generateItems)){
            generate.addSucceedingOperator(tpOrIndexScan);
          }
        } else {
          final BasicIndexScan bi = (BasicIndexScan) tpOrIndexScan;
          if(bi.getTriplePattern()!=null && bi.getTriplePattern().size()>0){
            final LinkedList<TriplePattern> matchingTPs = new LinkedList<TriplePattern>();
            for(final TriplePattern inIndexScan: bi.getTriplePattern()){
              if(BasicIndexRuleEvaluator.isMatching(inIndexScan, generateItems)){
                matchingTPs.add(inIndexScan);
                break;
              }
            }
            if(matchingTPs.size()>0){
              // modify BasicIndex in toBeConnectedTo! (delete tp in current bi, add new BasicIndex with tp, join both operators and additionally add tp for generate operator!)
              for(final TriplePattern tp: matchingTPs){
                final TriplePattern newTP = new TriplePattern(tp.getPos(0), tp.getPos(1), tp.getPos(2));
                newTP.recomputeVariables();
                generate.addSucceedingOperator(newTP);
                newTP.addPrecedingOperator(generate);

                if(bi.getTriplePattern().size()==1){
                  newTP.addSucceedingOperators(new LinkedList<OperatorIDTuple>(bi.getSucceedingOperators()));
                  for(final OperatorIDTuple opID: bi.getSucceedingOperators()){
                    opID.getOperator().addPrecedingOperator(newTP);
                  }
                } else {
                  bi.getTriplePattern().remove(tp);
                  final Join join = new Join();
                  join.setUnionVariables(bi.getUnionVariables());
                  bi.recomputeVariables();
                  tp.recomputeVariables();
                  final HashSet<Variable> joinVars = new HashSet<Variable>(tp.getUnionVariables());
                  joinVars.retainAll(bi.getUnionVariables());
                  join.setIntersectionVariables(joinVars);
                  for(final OperatorIDTuple opID: bi.getSucceedingOperators()){
                    final BasicOperator suc = opID.getOperator();
                    suc.removePrecedingOperator(bi);
                    suc.addPrecedingOperator(join);
                  }
                  join.setSucceedingOperators(bi.getSucceedingOperators());
                  bi.setSucceedingOperator(new OperatorIDTuple(join, 0));
                  join.addPrecedingOperator(bi);

                  final LinkedList<TriplePattern> tpList = new LinkedList<TriplePattern>();
                  tpList.add(tp);
                  final BasicIndexScan newIndex = ((Root)rootQuery).newIndexScan(new OperatorIDTuple(join, 1), tpList, bi.getGraphConstraint());
                  newIndex.recomputeVariables();
                  join.addPrecedingOperator(newIndex);
                  rootQuery.addSucceedingOperator(newIndex);
                  newIndex.addPrecedingOperator(rootQuery);
                  newTP.addSucceedingOperator(new OperatorIDTuple(join, 1));
                  join.addPrecedingOperator(newTP);

                  toBeConnectedTo.add(newIndex);
                }
              }
            }
          }
        }
      }
      if(generate.getSucceedingOperators().size()==0){
        // this generate operator is not connected to any other operator and thus can be deleted!
        deletePrecedingOperators(generate);
      }
    }

    rootInference.deleteParents();
    rootInference.setParents();
    rootInference.detectCycles();
    // determine those operators, which are not connected to the result operator (or an insert operator), and delete them
    final HashSet<BasicOperator> visited = new HashSet<BasicOperator>();
    final HashSet<BasicOperator> connectedOperators = new HashSet<BasicOperator>();
    final LinkedList<BasicOperator> path = new LinkedList<BasicOperator>();
    path.add(rootInference);
    BasicIndexRuleEvaluator.determineOperatorsConnectedWithResultOrInsert(rootInference, path, visited, connectedOperators);

    for(final BasicOperator bo: visited){
      if(!connectedOperators.contains(bo)){
        bo.removeFromOperatorGraphWithoutConnectingPrecedingWithSucceedingOperators();
      }
    }

    // add the first operations of the inference operator graph to the operator graph of the query
    for(final OperatorIDTuple rootChild: new LinkedList<OperatorIDTuple>(rootInference.getSucceedingOperators())){
      rootInference.removeSucceedingOperator(rootChild);
      final BasicOperator rootChildOperator = rootChild.getOperator();
      rootChildOperator.removePrecedingOperator(rootInference);
      rootChildOperator.addPrecedingOperator(rootQuery);
      if(rootChildOperator instanceof InsertIndexScan) {
        // these operators are used to insert facts/triples => should occur as leftmost operators after the root such that they are evaluated first!
        final LinkedList<OperatorIDTuple> list = new LinkedList<OperatorIDTuple>(rootQuery.getSucceedingOperators());
        list.addFirst(rootChild);
        rootQuery.setSucceedingOperators(list);
      } else {
        rootQuery.addSucceedingOperator(rootChild);
      }
    }
    rootQuery.deleteParents();
    rootQuery.setParents();
    rootQuery.detectCycles();
  }

  public static void determineOperatorsConnectedWithResultOrInsert(final BasicOperator currentOperator, final LinkedList<BasicOperator> currentPath, final HashSet<BasicOperator> visited, final HashSet<BasicOperator> connectedOperators){
    if(currentOperator instanceof Result || currentOperator instanceof Insert){
      BasicIndexRuleEvaluator.addToConnectedOperators(currentPath, connectedOperators);
    } else {
      if(visited.contains(currentOperator)){
        if(connectedOperators.contains(currentOperator)){
          BasicIndexRuleEvaluator.addToConnectedOperators(currentPath, connectedOperators);
        }
        return;
      } else {
        visited.add(currentOperator);
        for(final OperatorIDTuple opIDTuple: currentOperator.getSucceedingOperators()){
          final BasicOperator suc = opIDTuple.getOperator();
          currentPath.addLast(suc);
          BasicIndexRuleEvaluator.determineOperatorsConnectedWithResultOrInsert(suc, currentPath, visited, connectedOperators);
          currentPath.removeLast();
        }
      }
    }
  }

  private static void addToConnectedOperators(final Collection<BasicOperator> toBeAdded, final HashSet<BasicOperator> connectedOperators){
    for(final BasicOperator inPath: toBeAdded){
      if(!connectedOperators.contains(inPath)){
        connectedOperators.add(inPath);
        BasicIndexRuleEvaluator.addToConnectedOperators(inPath.getCycleOperands(), connectedOperators);
      } else {
        connectedOperators.add(inPath);
      }
    }
  }

  private static boolean isMatching(final TriplePattern tp, final Item[] generateItems){
    boolean flag=true;
    for(int i=0; i<3; i++){
      final Item a = generateItems[i];
      final Item b = tp.getPos(i);
      if(!a.isVariable() && !b.isVariable() && !a.equals(b)){
        flag=false;
        break;
      }
    }
    return flag;
  }

  public static void deletePrecedingOperators(final BasicOperator toDelete){
    if(toDelete.getSucceedingOperators().size()>0){
      // maybe result of this operation is somewhere else used => end of recursion
      return;
    }
    for(final BasicOperator parent: new LinkedList<BasicOperator>(toDelete.getPrecedingOperators())){
      parent.removeSucceedingOperator(toDelete);
      toDelete.removePrecedingOperator(parent);
      deletePrecedingOperators(parent);
    }
  }

  public static LinkedList<BasicOperator> determine1stLevelTriplePatternOrIndexScans(final BasicOperator rootQuery){
    final LinkedList<BasicOperator> resultlist = new LinkedList<BasicOperator>();
    determine1stLevelTriplePatternOrIndexScans(rootQuery, resultlist);
    return resultlist;
  }

  private static void determine1stLevelTriplePatternOrIndexScans(final BasicOperator rootQuery, final LinkedList<BasicOperator> resultlist) {
    for(final OperatorIDTuple child: rootQuery.getSucceedingOperators()){
      final BasicOperator childOperator = child.getOperator();
      if(childOperator instanceof TriplePattern || childOperator instanceof BasicIndexScan){
        resultlist.add(childOperator);
      } else if(childOperator instanceof PatternMatcher || childOperator instanceof Window){
        determine1stLevelTriplePatternOrIndexScans(childOperator, resultlist);
      }
    }
  }
}
TOP

Related Classes of lupos.rif.BasicIndexRuleEvaluator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.