Package de.fuberlin.wiwiss.d2rq.parser

Source Code of de.fuberlin.wiwiss.d2rq.parser.RelationBuilder

package de.fuberlin.wiwiss.d2rq.parser;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import de.fuberlin.wiwiss.d2rq.D2RQException;
import de.fuberlin.wiwiss.d2rq.algebra.AliasMap;
import de.fuberlin.wiwiss.d2rq.algebra.AliasMap.Alias;
import de.fuberlin.wiwiss.d2rq.algebra.Attribute;
import de.fuberlin.wiwiss.d2rq.algebra.Join;
import de.fuberlin.wiwiss.d2rq.algebra.OrderSpec;
import de.fuberlin.wiwiss.d2rq.algebra.ProjectionSpec;
import de.fuberlin.wiwiss.d2rq.algebra.Relation;
import de.fuberlin.wiwiss.d2rq.algebra.RelationImpl;
import de.fuberlin.wiwiss.d2rq.expr.Conjunction;
import de.fuberlin.wiwiss.d2rq.expr.Expression;
import de.fuberlin.wiwiss.d2rq.expr.SQLExpression;
import de.fuberlin.wiwiss.d2rq.sql.ConnectedDB;

/**
* TODO Describe this type
* TODO isUnique is not properly handled yet
*
* @author Richard Cyganiak (richard@cyganiak.de)
*/
public class RelationBuilder {
  private final ConnectedDB database;
  private Expression condition = Expression.TRUE;
  private Set<Join> joinConditions = new HashSet<Join>();
  private Set<Alias> aliases = new HashSet<Alias>();
  private final Set<ProjectionSpec> projections = new HashSet<ProjectionSpec>();
  private boolean isUnique = false;
  private List<OrderSpec> orderSpecs = new ArrayList<OrderSpec>();
  private int limit = Relation.NO_LIMIT;
  private int limitInverse = Relation.NO_LIMIT;
   
  public RelationBuilder(ConnectedDB database) {
    this.database = database;
  }
 
  public void setIsUnique(boolean isUnique) {
    this.isUnique = isUnique;
  }
 
  public void addOther(RelationBuilder other) {
    this.condition = this.condition.and(other.condition);
    this.joinConditions.addAll(other.joinConditions);
    this.aliases.addAll(other.aliases);
    this.projections.addAll(other.projections);
    this.isUnique = this.isUnique || other.isUnique;
    if (!other.orderSpecs.isEmpty()) {
      // Overwrite our ordering if the other builder is ordered
      this.orderSpecs = other.orderSpecs;
    }
    this.limit = Relation.combineLimits(limit, other.limit);
    this.limitInverse = Relation.combineLimits(limitInverse, other.limitInverse);
  }
 
  /**
   * Adds information from another relation builder to this one,
   * applying this builder's alias mappings to the other one.
   * 
   * @param other A relation builder that potentially uses aliases declared in this builder
   */
  public void addAliased(RelationBuilder other) {
    this.condition = this.condition.and(aliases().applyTo(other.condition));
    this.joinConditions.addAll(aliases().applyToJoinSet(other.joinConditions));
    this.projections.addAll(aliases().applyToProjectionSet(other.projections));
    Collection<Alias> newAliases = new ArrayList<Alias>();
    Collection<Alias> removedAliases = new ArrayList<Alias>();
    for (Alias alias : (Collection<Alias>) this.aliases) {
      Alias newAlias = other.aliases().originalOf(alias);
      if (!alias.equals(newAlias)) {
        removedAliases.add(alias);
      }
      newAliases.add(newAlias);
    }
    this.aliases.removeAll(removedAliases);
    this.aliases.addAll(newAliases);
    if (!other.orderSpecs.isEmpty()) {
      // Overwrite our ordering if the other builder is ordered
      this.orderSpecs = aliases().applyTo(other.orderSpecs);
    }
    this.limit = Relation.combineLimits(limit, other.limit);
    this.limitInverse = Relation.combineLimits(limitInverse, other.limitInverse);
  }
 
  public void addCondition(String condition) {
    this.condition = this.condition.and(SQLExpression.create(condition));
  }
 
  public void addCondition(Expression condition) {
    this.condition = this.condition.and(condition);
  }
 
  public void addAlias(Alias alias) {
    this.aliases.add(alias);
  }
 
  public void addAliases(Collection<Alias> aliases) {
    this.aliases.addAll(aliases);
  }
 
  public void addJoinCondition(Join joinCondition) {
    this.joinConditions.add(joinCondition);
  }
 
  public void addProjection(ProjectionSpec projection) {
    this.projections.add(projection);
  }
 
  public void setOrderSpecs(List<OrderSpec> orderSpecs) {
      this.orderSpecs = orderSpecs;
  }
 
  public void setLimit(int limit) {
      this.limit = limit;
  }
 
  public void setLimitInverse(int limitInverse) {
      this.limitInverse = limitInverse;
  }
 
  public Relation buildRelation() {
    if (!isUnique) {
      for (ProjectionSpec projection: projections) {
        for (Attribute column: projection.requiredAttributes()) {
          if (!database.columnType(column).supportsDistinct()) {
            throw new D2RQException("The datatype of " + column + " (" +
                database.columnType(column) + ") does not support " +
                "SELECT DISTINCT and therefore cannot be used in a " +
                "context where d2rq:containsDuplicates is true.",
                D2RQException.DATATYPE_DOES_NOT_SUPPORT_DISTINCT);
          }
        }
      }
    }
    AliasMap aliases = aliases();
   
    // The contract is that all projections are required (must not be NULL).
    // So let's add them all as soft conditions. The soft condition for
    // a non-nullable column is TRUE.
    Collection<Expression> softConditions = new HashSet<Expression>(projections.size());
    for (ProjectionSpec projection: projections) {
      softConditions.add(projection.notNullExpression(database, aliases));
    }
   
    return new RelationImpl(
        database,
        aliases,
        this.condition,
        Conjunction.create(softConditions),
        this.joinConditions,
        this.projections,
        this.isUnique,
        this.orderSpecs,
        this.limit,
        this.limitInverse);
  }
 
  public AliasMap aliases() {
    return new AliasMap(this.aliases);
  }
}
TOP

Related Classes of de.fuberlin.wiwiss.d2rq.parser.RelationBuilder

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.