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

com.weaverplatform.sp4rql.model.solution.SolutionFactory Maven / Gradle / Ivy

package com.weaverplatform.sp4rql.model.solution;

import com.weaverplatform.sp4rql.error.ParseException;
import com.weaverplatform.sp4rql.model.expression.ExpressionUnit;
import com.weaverplatform.sp4rql.model.restriction.Sp4rqlRestriction;
import com.weaverplatform.sp4rql.model.scope.ScopeQuery;
import com.weaverplatform.sp4rql.model.scope.Sp4rqlScope;
import com.weaverplatform.sp4rql.model.token.VariableToken;

public class SolutionFactory {

  // When this function is called we can be sure all scopes and restrictions are instantiated and linked
  public static void buildSolutions(Sp4rqlScope scope) {
    scope.resetSolutions();
    buildSubSolutions(scope);
    updateResolvesTo(scope);
  }

  private static void buildSubSolutions(Sp4rqlScope scope) {
    // Register all tokens from restrictions in this scope
    for(Sp4rqlRestriction restriction : scope.getRestrictions()) {
      for(VariableToken token : restriction.getExposedVariables()) {
        Sp4rqlSolution solution = registerToken(token, scope);
        solution.addRestriction(restriction);
      }
    }
    // Register all tokens from select mappings
    if(scope instanceof ScopeQuery) {
      ScopeQuery scopeQuery = (ScopeQuery) scope;
      for(VariableToken token : scopeQuery.getSelectVariables()) {
        ExpressionUnit expression = scopeQuery.getSelectExpression(token);
        // Variable expression is null for normal selects
        if(expression != null) {
          if(!expression.isAggregate()) {
            throw new ParseException("Expected an expression with a aggregate function");
          }
          Sp4rqlSolution solution = registerToken(token, scope);
          solution.setAggregationExpression(expression);
        }
      }
    }
    // Register all tokens from 'scoped expressions' (only exists and not exists) in this scope
    for(Sp4rqlScope expressionScope : scope.getExpressionScopes()) {
      for(VariableToken token : expressionScope.getExposedVariables()) {
        Sp4rqlSolution solution = registerToken(token, scope);
        solution.addRestriction(expressionScope);
      }
    }
    // Analyse all scopes
    for(Sp4rqlSolution solution : scope.getSolutions()) {
      solution.analyseTypes();
    }
    // Visit all sub-scopes recursively
    for(Sp4rqlRestriction restriction : scope.getRestrictions()) {
      if(restriction instanceof Sp4rqlScope) {
        buildSubSolutions((Sp4rqlScope) restriction);
      }
    }
    for(Sp4rqlRestriction restriction : scope.getExpressionScopes()) {
      if(restriction instanceof Sp4rqlScope) {
        buildSubSolutions((Sp4rqlScope) restriction);
      }
    }
  }

  public static Sp4rqlSolution registerToken(VariableToken token, Sp4rqlScope scope) {
    Sp4rqlSolution solution = scope.getSolution(token);
    if(solution != null) {
      return solution;
    }
    boolean escalate = false;
    if(scope.inScope() != null) {
      escalate |= scope.getExposedVariables().contains(token);
    }
    if(escalate) {
      solution = registerToken(token, scope.inScope());
      scope.setSolution(token, solution);
      return solution;
    } else {
      solution = new Sp4rqlSolution(token);
      solution.setScope(scope);
      scope.setSolution(token, solution);
      return solution;
    }
  }

  private static void updateResolvesTo(Sp4rqlScope scope) {
    // Update resolveTo values
    for(Sp4rqlRestriction restriction : scope.getRestrictions()) {
      if(restriction instanceof Sp4rqlScope) {
        updateResolvesTo((Sp4rqlScope) restriction);
      }
    }

    // Make sure all equalSolutions are attuned
    for(Sp4rqlSolution solution : scope.getSolutions()) {
      solution.tuneEqualSolutions();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy