Package de.fuberlin.wiwiss.d2rq.algebra

Source Code of de.fuberlin.wiwiss.d2rq.algebra.TripleRelation

package de.fuberlin.wiwiss.d2rq.algebra;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.sparql.core.Var;

import de.fuberlin.wiwiss.d2rq.expr.Expression;
import de.fuberlin.wiwiss.d2rq.nodes.NodeMaker;

/**
* A collection of virtual triples obtained by applying a {@link Relation} to a
* database, and applying {@link NodeMaker}s for subject, predicate and object
* to each result row. This is implemented as a stateless wrapper around a
* {@link NodeRelation}.
*
* @author Chris Bizer chris@bizer.de
* @author Richard Cyganiak (richard@cyganiak.de)
*/
public class TripleRelation extends NodeRelation {
  public static final Var SUBJECT = Var.alloc("subject");
  public static final Var PREDICATE = Var.alloc("predicate");
  public static final Var OBJECT = Var.alloc("object");

  private static final Set<Var> SPO =
    new HashSet<Var>(Arrays.asList(new Var[]{SUBJECT, PREDICATE, OBJECT}));
 
  private static final TripleRelation EMPTY = fromNodeRelation(NodeRelation.empty(SPO));
 
  private static TripleRelation fromNodeRelation(NodeRelation relation) {
    if (relation instanceof TripleRelation) return (TripleRelation) relation;
    if (!relation.variables().equals(SPO)) {
      throw new IllegalArgumentException(
          "Not a TripleRelation header: " + relation.variables());
    }
    return new TripleRelation(relation.baseRelation(),
        relation.nodeMaker(SUBJECT), relation.nodeMaker(PREDICATE), relation.nodeMaker(OBJECT));
  }
 
  public TripleRelation(Relation baseRelation,
      final NodeMaker subjectMaker, final NodeMaker predicateMaker, final NodeMaker objectMaker) {
    super(baseRelation, new HashMap<Var,NodeMaker>() {{
      put(SUBJECT, subjectMaker);
      put(PREDICATE, predicateMaker);
      put(OBJECT, objectMaker);
    }});
  }
 
  @Override
  public TripleRelation orderBy(Var variable, boolean ascending) {
    return fromNodeRelation(super.orderBy(variable, ascending));
  }

  @Override
  public TripleRelation limit(int limit) {
    return fromNodeRelation(super.limit(limit));
  }

  public TripleRelation selectTriple(Triple t) {
    MutableRelation newBase = new MutableRelation(baseRelation());
    NodeMaker s = nodeMaker(SUBJECT).selectNode(t.getSubject(), newBase);
    if (s.equals(NodeMaker.EMPTY)) return null;
    NodeMaker p = nodeMaker(PREDICATE).selectNode(t.getPredicate(), newBase);
    if (p.equals(NodeMaker.EMPTY)) return null;
    NodeMaker o = nodeMaker(OBJECT).selectNode(t.getObject(), newBase);
    if (o.equals(NodeMaker.EMPTY)) return null;
    Set<ProjectionSpec> projections = new HashSet<ProjectionSpec>();
    projections.addAll(s.projectionSpecs());
    projections.addAll(p.projectionSpecs());
    projections.addAll(o.projectionSpecs());
    newBase.project(projections);
    if (!s.projectionSpecs().isEmpty() && o.projectionSpecs().isEmpty()) {
        newBase.swapLimits();
    }
    return new TripleRelation(newBase.immutableSnapshot(), s, p, o);
  }

  /**
   * Creates a {@link NodeRelation} by applying a triple pattern
   * to the TripleRelation. If the triple contains variables, then
   * the variables will be bound to the corresponding values
   * in the resulting NodeRelation. {@link Node#ANY} will be
   * converted to a variable "subject", "predicate", "object"
   * depending on its position in the triple pattern.
   *
   * For example, selecting (?x :name ?name) would produce a
   * NodeRelation with ?x bound to the subjects and ?name bound to the
   * objects of this TripleRelation.
   *
   * TODO This is never called at the moment. Why!?
   *
   * @param t A triple pattern involving variables
   * @return A NodeRelation over the variables occurring in the triple pattern
   */
  public TripleRelation selectWithVariables(Triple t) {
    // Select non-variable parts of the triple
    TripleRelation selected = selectTriple(t);
   
    // Replace Node.ANY with "subject", "predicate", "object"
    Node s = t.getSubject() == Node.ANY ? SUBJECT : t.getSubject();
    Node p = t.getPredicate() == Node.ANY ? PREDICATE : t.getPredicate();
    Node o = t.getObject() == Node.ANY ? OBJECT : t.getObject();
   
    // Collect variable names and their bound node makers
    VariableConstraints nodeMakers = new VariableConstraints();
    nodeMakers.addIfVariable(s, nodeMaker(SUBJECT), baseRelation().aliases());
    nodeMakers.addIfVariable(p, nodeMaker(PREDICATE), baseRelation().aliases());
    nodeMakers.addIfVariable(o, nodeMaker(OBJECT), baseRelation().aliases());

    // Did the same variable occur more than once in the pattern, rendering it unsatisfiable?
    if (!nodeMakers.satisfiable()) {
      return TripleRelation.EMPTY;
    }
   
    MutableRelation mutator = new MutableRelation(selected.baseRelation());

    Expression constraint = nodeMakers.constraint();
    if (!constraint.isTrue()) {
      // Same variable occured more than once, so we add a constraint to the base relation
      mutator.select(constraint);
    }
   
    mutator.project(nodeMakers.allProjections());
    return fromNodeRelation(new NodeRelation(
        mutator.immutableSnapshot(), nodeMakers.toMap()));
  }
}
TOP

Related Classes of de.fuberlin.wiwiss.d2rq.algebra.TripleRelation

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.